目录
线程的创建
1.对函数创建线程
2.对类里面创建线程
3.对成员函数创建变量
4.多线程的创立
Mutex
1.一般互斥锁
2.lock_guard
3.unique_lock
条件变量
线程的创建
线程的创建需要#include ,格式为thread mythread(....)
1.对函数创建线程
线程的创建需要#include
格式为thread mythread(function,variable1,variable2,...)
#include#include using namespace std; void fuction(int a, int b) { cout << "enter the subthread:"; cout << a << b << endl; } int main(void) { cout << "in main thread" << endl; thread mythread(fuction, 2, 9); mythread.join(); cout << "in main thread" << endl; }
2.对类里面创建线程
格式为thread mythread(classvariable,variables);这里似乎一定要重载括号。
#include#include #include using namespace std; class X { public: X() { cout << "constructor!" << endl; } X(const X& m) { cout << "copy constructor called !" << endl; } void operator()(int a) // 重载括号运算符。如果无参则为void operator()(){...} { cout << "start!" << a << endl; } }; int main() { X a; thread p(a, 4); //以对象a创建线程,并传递参数4,无参的话直接省略第二个参数,更多的参数直接加在后面 p.join(); return 0; }
3.对成员函数创建变量
格式为thread mythread(&class::function,&classvariable,variables_of_function)
#include#include #include using namespace std; class X { public: X() { cout << "constructor!" << endl; } X(const X& m) { cout << "copy constructor called !" << endl; } void coutdata(int a, int d) { cout << a << '&' << d << endl; } }; int main() { X a; thread p(&X::coutdata,&a,3,4); //以对象coutdata创建线程,并传递参数3、4, //无参的话直接省略第二个参数,更多的参数直接加在后面 p.join(); return 0; }
4.多线程的创立
只要同时使用多个thread创建,再逐一join便可。mythread.join();表示阻塞主线程,等子线程运行完再运行主线程,可join多个子线程。这时便进行了多线程运行,如果两个线程同时对一个变量进行操作则需要下面的mutex。C++ 多线程join()和detach()的理解_皮皮#2500-CSDN博客_c++线程detach
Mutex
锁是把在lock和unlock之间的代码锁起来,如果涉及到几个线程共同涉及到一个变量,锁便起了大作用。需要#include
#include#include #include #include #include using namespace std; class List { private: list
mylist; mutex mlock; int i = 0; public: void WriteList() { while (i < 1000) { mylist.push_back(i++); } return; } void showList() { for (auto p = mylist.begin(); p != mylist.end(); p++) { cout << (*p) << " "; } cout << endl; cout << "size of list : " << mylist.size() << endl; return; } }; int main() { List mlist; thread pwrite0(&List::WriteList, &mlist); thread pwrite1(&List::WriteList, &mlist); pwrite0.join(); pwrite1.join(); cout << "threads end!" << endl; mlist.showList(); //子线程结束后主线程打印list return 0; }
改自:
1.一般互斥锁
1. 原子性:把一个互斥量锁定为一个原子操作,这意味着如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量;
2. 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量;
3. 非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
1. 原子性:把一个互斥量锁定为一个原子操作,这意味着如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量;
2. 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量;
3. 非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
互斥锁将mlock.lock()和mlock.unlock()之间锁住;
#include#include #include #include #include using namespace std; class List { private: list
mylist; mutex mlock; int i = 0; public: void WriteList() { while (i < 1000) { mlock.lock(); if (i >= 10000) { mlock.unlock(); //退出之前必须先解锁 break; } mylist.push_back(i++); mlock.unlock(); } return; } void showList() { for (auto p = mylist.begin(); p != mylist.end(); p++) { cout << (*p) << " "; } cout << endl; cout << "size of list : " << mylist.size() << endl; return; } }; int main() { List mlist; thread pwrite0(&List::WriteList, &mlist); thread pwrite1(&List::WriteList, &mlist); pwrite0.join(); pwrite1.join(); cout << "threads end!" << endl; mlist.showList(); //子线程结束后主线程打印list return 0; }
2.lock_guard
lock_guard就是一个类,它会在lock_guard的构造函数中加锁,而在析构函数中解锁,也就是说,只要创建一个lock_guard的对象,就相当于lock()了,而该对象析构时,就自动调用unlock()了。
void WriteList()
{
while(i<10000)
{
lock_guard guard(mlock); //创建lock_guard的类对象guard,用互斥量m来构造
//mlock.lock();
if (i >= 10000)
{
//mlock.unlock(); //由于有了guard,这里就无需unlock()了
break;
}
mylist.push_back(i++);
//mlock.unlock();
}
return;
}
3.unique_lock
unique_lock和上面的规则差不多,不过他生命期内允许手动加锁和释放锁。图来自:
这里说明一下unique_lock是给原先有的一个mutex类型(比如叫mlock)再套上一层,
unique
locker(mlock)。使mlock变为名字为locker的特殊锁,对其解锁时用的是: locker.unlock();而非mlock.unlock();
条件变量
copy_from
条件变量使用“通知—唤醒”模型,生产者生产出一个数据后通知消费者使用,消费者在未接到通知前处于休眠状态节约CPU资源;当消费者收到通知后,赶紧从休眠状态被唤醒来处理数据,使用了事件驱动模型,在保证不误事儿的情况下尽可能减少无用功降低对资源的消耗。
- 那个通知“条件已满足”的线程(或多个线程之一)必须调用notify_one()或notify_all(),以便条件满足时唤醒处于等待中的一个条件变量;
- 那个等待"条件被满足"的线程必须调用wait(),可以让线程在条件未被满足时陷入休眠状态,当接收到通知时被唤醒去处理相应的任务
#include#include //双端队列 #include #include using namespace std; deque q; mutex mu; condition_variable cond; void productor() { int count = 10; while (count > 0) { unique_lock locker(mu); q.push_front(count); locker.unlock(); cond.notify_one(); this_thread::sleep_for(chrono::seconds(1)); count--; } } void consumer() { int data = 0; while (data != 1) { unique_lock locker(mu); while (q.empty()) { cond.wait(locker); } data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } } int main(void) { thread t1(productor); thread t2(consumer); t1.join(); t2.join(); return 0; }



