C++温故补缺(十七):mutex类
mutex类
mutex类是C++中最基本的互斥量。它提供了基本的上锁与解锁函数,lock(),unlock()以及try_lock()。
lock()与unlock():
下面模拟之前说过的打印机的情况,就是多线程访问打印机,其中A线程在装入信息后被阻塞,打印机中的数据就会被线程B覆盖,当A恢复执行时,打印机中的数据仍然是B的数据。
#include<iostream>
#include<thread>
using namespace std;
string printstr;//模拟打印机装入信息
void printer(string str){
printstr=str;
this_thread::sleep_for(chrono::seconds(1));//模拟线程被阻塞
for(int i=0;i<3;i++)
cout<<printstr<<endl;
}
int main(){
thread th1(printer,"Hello");
thread th2(printer,"world");
th1.join();
th2.join();
}
可以看到打印机打印了6次th2线程的数据。想要获取正确的信息,就要用互斥锁,在打印前加锁,打印后解锁。
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex plocker;//打印机锁
string printstr;//模拟打印机装入信息
void printer(string str){
plocker.lock();//加锁
printstr=str;
this_thread::sleep_for(chrono::seconds(1));//模拟线程被阻塞
for(int i=0;i<3;i++)
cout<<printstr<<endl;
plocker.unlock();//解锁
}
int main(){
thread th1(printer,"Hello");
thread th2(printer,"world");
th1.join();
th2.join();
}
就获得了正确的打印结果
try_lock()
- try_lock()是尝试上锁,有两种情况:
-
锁空闲,返回true,并加锁
-
锁已经其他线程获取,返回false
模拟apt安装包时,另外一个线程等待的情况:
#include<iostream>
#include<thread>
#include<mutex>
#include<unistd.h>//sleep函数
using namespace std;
mutex aptlocker;//模拟apt锁
void installer(string str){
while(!aptlocker.try_lock()){
cout<<"waitting for other installing thread"<<endl;
}
cout<<"installing package:"<<str<<endl;
sleep(0.5);
aptlocker.unlock();
}
int main(){
thread th1(installer,"vim");
thread th2(installer,"stacer");
th1.join();
th2.join();
}
- 另外try_lock()还可以给多个互斥量加锁,格式:
int try_lock(mutex1,mutex2,mutex3...);
如果所有互斥量都加锁成功,则返回-1。当首次遇到加锁失败的互斥量时,停止对后续互斥量的加锁,并解锁前面的互斥量,返回首个加锁失败的互斥量的序号。 (Attempts to lock all the objects passed as arguments using their try_lock member functions (non-blocking).
The function calls the try_lock member function for each argument (first a, then b, and eventually the others in cde, in the same order), until either all calls are successful, or as soon as one of the calls fails (either by returning false
or throwing an exception).
If the function ends because a call fails, unlock is called on all objects for which the call to try_lock was successful, and the function returns the argument order number of the object whose lock failed. No further calls are performed for the remaining objects in the argument list.)from cplusplus.
如:
mutex locker1,locer2,locker3;
locker2.lock();
try_lock(locker1,locker2,locker3);
- lock()和try_lock()的区别
lock()是以阻塞的方式获取锁,而try_lock()是非阻塞式的。当线程请求被占用的锁时,用lock方式请求,会阻塞当前线程,无限时间,直到锁被释放。这就是死锁产生的直接原因,如果被占用的锁没有释放,那么请求的线程会永久地阻塞。
try_lock()方式请求锁时,会有一个设定好的最大时间,当在这个时间内没有获取到锁,线程会放弃请求锁,直接继续执行后续的代码。
了解更多:wait for single object函数.
- 所以有时候try_lock()并不能同步,如果是严格的同步程序,最好用lock();
如:之前打印机的模拟例子,使用互斥锁得到了正确的结果,如果是try_lock():
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex plocker;//打印机锁
string printstr;//模拟打印机装入信息
void printer(string str){
plocker.try_lock();//加锁
printstr=str;
this_thread::sleep_for(chrono::seconds(1));//模拟线程被阻塞
for(int i=0;i<3;i++)
cout<<printstr<<endl;
plocker.unlock();//解锁
}
int main(){
thread th1(printer,"Hello");
thread th2(printer,"world");
th1.join();
th2.join();
}
try_lock_for和try_lock_until
类似this_thread_for/until,参数也是时间
本文来自博客园,作者:Tenerome,转载请注明原文链接:https://www.cnblogs.com/Tenerome/p/cppreview17.html