标签:占用 using cout release 会同 所有权 防止 上下 href
@
在多线程环境中,有多个线程竞争同一个公共资源,就很容易引发线程安全的问题。因此就需要引入锁的机制,来保证任意时候只有一个线程在访问公共资源。
包含头文件#include <mutex>
步骤:1.lock(),2.操作共享数据,3.unlock()。
lock()和unlock()要成对使用,不能重复上锁和解锁。本质就是lock~unlock之间的程序(数据)不会同时调用、修改。
#include <iostream>
#include <thread>
#include <mutex>
#include <list>
using namespace std;
list<int> test_list;
mutex my_mutex;
void in_list(){
for(int num=0;num<1000000000000000000;num++){
my_mutex.lock();
cout<<"插入数据: "<<num<<endl;
test_list.push_back(num);
my_mutex.unlock();
}
}
void out_list(){
for(int num=0;num<1000000000000000000; ++num){
my_mutex.lock();
if(!test_list.empty()){
int tmp = test_list.front();
test_list.pop_front();
cout<<"取出数据:"<<tmp<<endl;
}
my_mutex.unlock();
}
}
int main()
{
thread in_thread(in_list);
thread out_thread(out_list);
in_thread.join();
out_thread.join();
cout << "Hello World!" << endl;
return 0;
}
lock_guard构造函数执行了mutex::lock(),在作用域结束时,自动调用析构函数,执行mutex::unlock()
#include <iostream>
#include <thread>
#include <mutex>
#include <list>
using namespace std;
list<int> test_list;
mutex my_mutex;
void in_list(){
for(int num=0;num<1000000000000000000;num++){
std::lock_guard<std::mutex> my_guard(my_mutex);
cout<<"插入数据: "<<num<<endl;
test_list.push_back(num);
}
}
void out_list(){
for(int num=0;num<1000000000000000000; ++num){
std::lock_guard<std::mutex> my_guard(my_mutex);
if(!test_list.empty()){
int tmp = test_list.front();
test_list.pop_front();
cout<<"取出数据:"<<tmp<<endl;
}
}
}
int main()
{
thread in_thread(in_list);
thread out_thread(out_list);
in_thread.join();
out_thread.join();
cout << "Hello World!" << endl;
return 0;
}
std::lock_guard<std::mutex> my_guard(my_mutex,std::adopt_lock);
加入adopt_lock后,在调用lock_guard的构造函数时,不再进行lock();
adopt_guard为结构体对象,起一个标记作用,表示这个互斥量已经lock(),不需要在lock()。
unique_lock想比于lock_guard,都是基于RAII思想的,也支持std::lock_guard的功能,但是区别在于它提供更多的成员函数,比如:lock(),unlock()使用更加灵活,并且可以和condiction_variable一起使用控制线程同步。但是效率差一点,内存占用多一点。
#include <iostream>
#include <thread>
#include <mutex>
#include <list>
using namespace std;
list<int> test_list;
mutex my_mutex;
void in_list(){
for(int num=0;num<1000000000000000000;num++){
std::unique_lock<std::mutex> my_guard(my_mutex);
cout<<"插入数据: "<<num<<endl;
test_list.push_back(num);
}
}
void out_list(){
for(int num=0;num<1000000000000000000; ++num){
std::unique_lock<std::mutex> my_guard(my_mutex);
if(!test_list.empty()){
int tmp = test_list.front();
test_list.pop_front();
cout<<"取出数据:"<<tmp<<endl;
}
}
}
int main()
{
thread in_thread(in_list);
thread out_thread(out_list);
in_thread.join();
out_thread.join();
cout << "Hello World!" << endl;
return 0;
}
1) std::adopt_lock:
- 表示这个互斥量已经被lock(),即不需要在构造函数中lock这个互斥量了。
- 前提:必须提前lock
- lock_guard中也可以用这个参数
2) std::try_to_lock:
#include <iostream>
#include <thread>
#include <mutex>
#include <list>
using namespace std;
list<int> test_list;
mutex my_mutex;
void in_list(){
for(int num=0;num<10000;num++){
std::unique_lock<std::mutex> my_unique(my_mutex, std::try_to_lock);
if(my_unique.owns_lock()){
cout<<"插入数据: "<<num<<endl;
test_list.push_back(num);
}
else{
cout<<"没能拿到锁,只能干点别的事"<<endl;
}
}
}
void out_list(){
for(int num=0;num<10000; ++num){
std::unique_lock<std::mutex> my_unique(my_mutex);
std::chrono::seconds dura(1);
std::this_thread::sleep_for(dura);
if(!test_list.empty()){
int tmp = test_list.front();
test_list.pop_front();
cout<<"取出数据:"<<tmp<<endl;
}
else {
cout<<"已经空了"<<endl;
}
}
}
int main()
{
thread in_thread(in_list);
thread out_thread(out_list);
in_thread.join();
out_thread.join();
cout << "Hello World!" << endl;
return 0;
}
3) std::defer_lock:
(前三个与std::defer_lock联合使用)
1)lock():加锁
unique_lock<mutex> myUniLock(myMutex, defer_lock);
myUniLock.lock();
作用是:不用自己unlock();
2)unlock():解锁。
unique_lock<mutex> myUniLock(myMutex, defer_lock);
myUniLock.lock();
//处理一些共享代码
myUniLock.unlock();
//处理一些非共享代码
myUniLock.lock();
//处理一些共享代码
作用:因为一些非共享代码要处理,可以暂时先unlock(),用其他线程把它们处理了,处理完后再lock()。
3)try_lock():尝试给互斥量加锁
如果拿不到锁,返回false,否则返回true。用法和前面的try_to_lock参数一致。
4)release():释放unique_lock所管理的mutex对象指针
myUniLock(myMutex)
相当于把myMutex和myUniLock绑定在了一起,release()就是解除绑定,返回它所管理的mutex对象的指针,并释放所有权mutex* ptx =myUniLock.release()
:ptx->unlock();
unique_lock myUniLock(myMutex);
把myMutex和myUniLock绑定在了一起,也就是myUniLock拥有myMutex的所有权// myUniLock拥有myMutex的所有权,myUniLock可以把自己对myMutex的所有权转移,但是不能复制。
unique_lock myUniLock2(std::move(myUniLock));
//现在myUniLock2拥有myMutex的所有权。
unique_lock<mutex> aFunction()
{
unique_lock<mutex> myUniLock(myMutex);
//移动构造函数那里讲从函数返回一个局部的unique_lock对象是可以的
//返回这种局部对象会导致系统生成临时的unique_lock对象,并调用unique_lock的移动构造函数
return myUniLock;
}
std::lock(mutex1,mutex2……)
:一次锁定多个互斥量(一般这种情况很少),用于处理多个互斥量。死锁至少有两个互斥量mutex1,mutex2。
只要保证多个互斥量上锁的顺序一样就不会造成死锁。
lock的代码段越少,执行越快,整个程序的运行效率越高。
C++ 多线程 (4) 互斥量(mutex)与锁(lock)
标签:占用 using cout release 会同 所有权 防止 上下 href
原文地址:https://www.cnblogs.com/long5683/p/12997011.html