C++多线程编程:其六、unique_lock的使用

文章讲述了C++中使用mutex时可能出现的异常导致死锁问题,介绍了基于RAII的unique_lock和lock_guard如何自动解锁以避免死锁,并比较了两者的特点。通过unique_lock的灵活性和可临时解锁特性,解决了死锁问题。
摘要由CSDN通过智能技术生成

一、异常导致没有解锁

mutex对象需要手动解锁。但是如果在解锁之前抛出来异常,就会导致解锁逻辑没有执行。当前线程就会一直占有互斥量,其它线程就一直无法得到互斥量,就无法执行,看代码:

#include <iostream>
#include <thread>
#include <mutex>
#include <stdexcept>

std::mutex mtx;

void print_event(int x)
{
    if(x%2==0)
        std::cout << x << " is even\n";
    else
        throw (std::logic_error("not even"));

}

void print_thread_id(int id)
{
    try{
        mtx.lock();
        print_event(id);
        mtx.unlock();
    }
    catch(std::logic_error&)
    {
        std::cout << "[exception caught]\n";
    }
}

int main(int argc,char **argv)
{
    std::thread threads[10];
    for(int i=0;i<10;i++)
    {
        threads[i]=std::thread(print_thread_id,i+1);
    }
    for (auto& th : threads) th.join();
    return 0;

}

执行后会发现程序被卡主,因为发生了死锁。

二、基于RAII思想的unique_lock

unique_lock在构造的时候传入mutex变量,对mutex变量加锁。在析构的时候对这个mutex变量解锁,从而实现了自动解锁。print_thread_id函数的代码可以替换为::

void print_thread_id(int id)
{
    try{
        std::unique_lock<std::mutex> ul(mtx);
        print_event(id);
    }
    catch(std::logic_error&)
    {
        std::cout << "[exception caught]\n";
    }
}

输出结果:

[exception caught]
[exception caught]
2 is even
4 is even
[exception caught]
6 is even
[exception caught]
8 is even
[exception caught]
10 is even

死锁解除。

三、unique_lock和lock_guard的区别

1、unique_lock与lock_guard都能实现自动加锁和解锁,但是前者更加灵活,能实现更多的功能。
2、unique_lock可以进行临时解锁和再上锁,如在构造对象之后使用lck.unlock()就可以进行解锁, lck.lock()进行上锁,而不必等到析构时自动解锁。lock_guard是不支持手动释放的。
3、一般来说,使用unique_lock比较多,除非追求极致的性能才会考虑使用lock_guard。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值