c++的mutex的库函数还是比较好用的,介绍两种加锁方式,自动的和手动的。
1 自动锁
名字叫做自动锁,但是还是要注意一下加锁位置的,不然线程不知道什么时候解锁,会导致死锁
一般来说我们都会有个信号量来作为标记,每次运行临界区代码之前先看看信号量。
检测信号量一般使用忙等待的方式检测。
大致代码形式如下:
void f() { //错误加锁位置 //如何把锁加到这里,那么整个while循环锁都会是锁着的,并且while循环不会结束,锁也就不开,导致死锁 while (1) { //正确加锁位置 //把锁加到这个地方,每次进入while循环的代码段时,锁会锁上, //while循环的代码段经过一个循环结束时,锁会打开,这样就不会死锁了 if (signal) { ''' 临界区 ''' } } }
正确样例:
// thread2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <thread> #include <list> #include <algorithm> #include <mutex> using namespace std; // a global variable int flag = 0; // a global instance of std::mutex to protect global variable std::mutex myMutex; void a() { int n = 3; while(n) { std::lock_guard<std::mutex> guard(myMutex); if (flag == 0) { cout << "0 is " << flag << endl; flag = 1; n--; } } } void b() { int n = 3; while (n) { std::lock_guard<std::mutex> guard(myMutex); if (flag == 1) { cout << "1 is " << flag << endl; flag = 0; n--; } } } int main() { std::thread t1(a); std::thread t2(b); t1.join(); t2.join(); return 0; }
2 手动锁,如果逻辑比较复杂,想自己设计加锁开锁的时间,那么可以用手动锁
这个就是自己加了。
样例代码:
// thread2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <thread> #include <list> #include <algorithm> #include <mutex> using namespace std; // a global variable int flag = 0; // a global instance of std::mutex to protect global variable std::mutex myMutex; void c() { int n = 3; while (n) { if (flag == 0 && myMutex.try_lock()) { cout << "0 is " << flag << endl; flag = 1; n--; myMutex.unlock(); } } } void d() { int n = 3; while (n) { if (flag == 1 && myMutex.try_lock()) { cout << "1 is " << flag << endl; flag = 0; n--; myMutex.unlock(); } } } int main() { std::thread t1(c); std::thread t2(d); t1.join(); t2.join(); return 0; }