C++ mutex lock_guard unique_lock使用说明

1. std::mutex

类似函数std::recursive_mutex 允许同一个线程多次获取同一个互斥量

头文件#include <mutex>

mutex::lock(),给共享内存加锁

...

...  //待保护代码或者共享内存等等

...

mutex::unlock(),给共享内存解锁

比如:

std::mutex m;

m.lock();

...

m.unlock();

 

2. std::lock_guard<std::mutex> (模板类)

头文件#include <mutex>

比如:

1)

std::mutex m;

{

std::lock_gurad<std::mutex> lguard(m); //类中默认加锁作用域,作用域执行完毕类析构中自动解锁

... //作用域在大括号中,作用域结束,lguard自动unlock。

}

2)

std::mutex m;

{

m.lock();

std::lock_guard<std::mutex> lguard(m, std::adopt_lock); //使用adopt_lock选项默认为未加锁,但是执行完作用域类析构函数中自动解锁。

...  //作用域在大括号内,作用域结束,lguard自动unlock。

}

3)

std::mutex m;

{

std::lock_guard<std::mutex> lguard(m); //默认已经加锁

std::mutex *pmtx = lguard.release(); //解除lguard和m之间的关联关系,此时m已经加锁,并未解锁,所以后面需要解锁

...  //作用域在大括号内,作用域结束,lguard自动unlock。

pmtx->unlock();

}

 

3. std::unique_lock<std::mutex>

头文件#include <mutex>

  1. 拥有方法std::unique_lock<std::mutex>::owns_lock(),判断当前是否锁定该锁。
  2. 拥有方法std::unique_lock<std::mutex>::try_lock(),尝试加锁,如果返回true则加锁成功,否则加锁失败,不阻塞。
  3. 拥有方法std::unique_lock<std::mutex>::release(),返回它管理的mutex对象指针,并释放所有权;也就是说,这个unique_lock和mutex不在有关系。

比如:

1)

std::mutex m;

{

std::unique_lock<std::mutex> uguard(m); //类中默认加锁作用域,作用域执行完毕类析构中自动解锁

... //作用域在大括号中,作用域结束,uguard自动unlock。

}

2)

std::mutex m;

{

m.lock();

std::unique_lock<std::mutex> uguard(m, std::adopt_lock); //使用adopt_lock选项默认为未加锁,但是执行完作用域类析构函数中自动解锁。

...  //作用域在大括号内,作用域结束,uguard自动unlock。

}

3)

std::mutex m;

{

std::unique_lock<std::mutex> uguard(m, std::try_to_lock); //解决一个线程加锁后占用事件较长,另一个线程等待较长时间的问题

...  //作用域在大括号内,作用域结束,uguard自动unlock。

}

4)

std::mutex m;

{

std::unique_lock<std::mutex> uguard(m, std::defer_lock); //1. 解决线程临时需要释放锁,之后再次加锁的情况。2. 如果后面不使用lock和unlock功能和示例3一样。

uguard.lock(); //加锁

...  //作用域在大括号内,作用域结束,uguard自动unlock。

 

另外也可以手动lock和unlock。

uguard.unlock();

...

...

uguard.lock();

...

...

uguard.unlock();

}

5)

std::mutex m;

{

std::unique_lock<std::mutex> uguard(m, std::defer_lock); //1. 解决线程临时需要释放锁,之后再次加锁的情况。2. 如果后面不使用lock和unlock功能和示例3一样。

uguard.lock(); //加锁

...  //作用域在大括号内,作用域结束,uguard自动unlock。

 

if( uguard.owns_lock() == true){

... //加锁成功,执行共享内存代码

}

else{

... //加锁没有成功

}

}

6)

std::mutex m;

{

std::unique_lock<std::mutex> uguard(m, std::defer_lock); //1. 解决线程临时需要释放锁,之后再次加锁的情况。2. 如果后面不使用lock和unlock功能和示例3一样。

 

...  //作用域在大括号内,作用域结束,uguard自动unlock。

 

if(uguard.try_lock() == true){

... //加锁成功,执行共享内存代码

}

else{

... //加锁没有成功

}

}

7)

std::mutex m;

{

std::unique_lock<std::mutex> uguard(m); //默认已经加锁

std::mutex *pmtx = uguard.release(); //解除uguard和m之间的关联关系,此时m已经加锁,并未解锁,所以后面需要解锁

...  //作用域在大括号内,作用域结束,uguard自动unlock。

pmtx->unlock();

}

 

4. std::lock()函数

功能:一次加多把锁,避免死锁

头文件:#include <mutex>

比如:

1)

std::mutex m1, m2;

std::lock(m1, m2) //m1,m2同时上锁

... //访问共享变量

m1.unlock();

m2.unlock();

2)

std::mutex m1, m2;

std::lock(m1, m2) //m1,m2同时上锁

std::lock_guard<std::mutex> lguard1(m1, std::adopt_lock); //用lock_guard自动unlock锁

std::lock_guard<std::mutex> lguard2(m2, std::adopt_lock);

... //访问共享变量

//不再需要unlock锁m1和m2了

3)

std::mutex m1, m2;

std::lock(m1, m2) //m1,m2同时上锁

std::unique_guard<std::mutex> uguard1(m1, std::adopt_lock); //用lock_guard自动unlock锁

std::unique_guard<std::mutex> uguard2(m2, std::adopt_lock);

... //访问共享变量

//不再需要unlock锁m1和m2了

 

5. std::timed_mutex 带超时功能的独占互斥量

类似函数std::recursive_timed_mutex 允许同一个线程多次获取同一个互斥量

头文件#include <mutex>

  1. try_lock_for()函数:等待一段时间。如果拿到锁或者等待超时,就往下执行。
  2. try_lock_until()函数:参数是一个未来时间点,在未来一段时间内如果拿到锁就走下来;如果时间到了没有拿到锁,程序也走下来。

比如:

1)

std::timed_mutex m;

std::chrono::millisecond timeout(100);

if(m.try_lock_for(timeout)){ //程序等待100毫秒尝试拿锁,如果拿到锁执行if,否则else

... //拿到锁,执行互斥内容

m.unlock();

}

else{

... //没有拿到锁

}

2)

std::timed_mutex m;

std::chrono::millisecond timeout(100);

if(m.try_lock_until(std::chrono::steady_clock::now() + timeout)){ //程序从当前时间开始经过100毫秒时间,如果拿到锁,执行if,否则执行else

... //执行互斥内容

m.unlock();

}

else{

... //没有拿到锁

}

以上内容,详情查看文档

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在给定的代码示例中,`std::mutex`,`std::unique_lock`和`std::lock_guard`是C++中用于实现线程同步的标准库类。它们可以用于保护共享资源,以确保在多个线程同时访问该资源时不出现竞争条件。 `std::mutex`是一个互斥体,用于实现互斥锁。它可以在需要时锁定共享资源,并在不再需要访问时解锁它。在给定的代码示例中,`std::mutex mt`是一个互斥体对象。 `std::unique_lock`和`std::lock_guard`都是互斥锁的RAII(资源获取即初始化)封装类。它们提供了一种便捷的方式来锁定和解锁互斥锁。不同之处在于,`std::unique_lock`提供了更多的灵活性,可以在运行时选择锁定和解锁的时机,而`std::lock_guard`在构造时锁定互斥锁,在析构时解锁互斥锁。在给定的代码示例中,`std::lock_guard`和`std::unique_lock`都用于在执行特定代码块时锁定互斥锁,并在代码块结束时解锁它们。 在混用`std::mutex`,`std::unique_lock`和`std::lock_guard`时,可以根据具体的需求选择合适的组合。例如,如果您需要在代码块中灵活地锁定和解锁互斥锁,可以使用`std::unique_lock`。如果您只需要在代码块中锁定和解锁互斥锁,并且不需要灵活性,可以使用`std::lock_guard`。这些类可以根据需要混合使用,以提供更具表达力和适应性的线程同步代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++11多线程编程——lock_guardunique_lock](https://blog.csdn.net/m0_47313541/article/details/130480617)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值