C++并发编程(4):共享数据的问题、使用互斥量保护共享数据、死锁

在线程间共享数据

参考博客

线程间共享数据——使用互斥量保护共享数据

[c++11]多线程编程(四)——死锁(Dead Lock)

c****++多线程之死锁****

C++ 死锁及解决办法

共享数据的问题

设想你有一段时间和朋友合租公寓,公寓只有一个厨房和一个浴室。除非你们的感情格外深厚,否则不可能同时使用浴室。另外,假若朋友占用浴室很久,而你恰好也需要,便会感到不方便。类似地,假设你们使用的是组合烤箱,尽管可以同时烹饪,但若一人要烤香肠,同时另一人却要烘蛋糕,结果应该不会太好。并且,我们也清楚共用办公空间的烦恼:事情还没做完,有人却借走了工作所需之物,或者半成品被别人擅自更改

线程亦如此。若在线程之间共享数据,我们需要遵循规范:具体哪个线程按何种方式访问什么数据;还有,一旦改动了数据,如果牵涉到其他线程,它们要在何时以什么通信方式获得通知。同一进程内的多个线程之间,虽然可以简单易行地共享数据,但这不是绝对的优势,有时甚至是很大的劣势。不正确地使用共享数据,是产生与并发有关的错误的一个很大的诱因,其后果远比“香肠口味的蛋糕”严重

恶性条件竞争

诱发恶性条件竞争的典型场景是,要完成一项操作,却需改动两份或多份不同的数据,如上例中的两个链接指针。因为操作涉及两份独立的数据,而它们只能用单独的指令改动,当其中一份数据完成改动时,别的线程有可能不期而访。因为满足条件的时间窗口短小,所以条件竞争往往既难察觉又难复现。若改动操作是由连续不间断的CPU指令完成的,就不太有机会在任何的单次运行中引发问题,即使其他线程正在并发访问数据。只有按某些次序执行指令才可能引发问题。随着系统负载加重及执行操作的次数增多,这种次序出现的机会也将增加。“屋漏偏逢连夜雨”几乎难以避免,且这些问题偏偏会在最不合时宜的情况下出现。恶性条件竞争普遍“挑剔”出现的时机,当应用程序在调试环境下运行时,它们常常会完全消失,因为调试工具影响了程序的内部执行时序,哪怕只影响一点点

使用互斥量保护共享数据

在访问共享数据前,开发者可使用互斥量将相关数据锁住,并于访问结束后将数据解锁。因此,线程库需要保证当一个线程使用特定互斥量锁住共享数据时,其他线程仅可在数据被解锁后才能访问

lock()、 unlock()上锁解锁

C++中通过实例化std::mutex创建互斥量,通过调用成员函数lock()进行上锁,unlock()进行解锁

在实际中必须成对使用,一旦在函数中用了lock,则在函数出口处必须调用unlock

mutex my_mutex;
int a = 1;
bool func()
{
      
    my_mutex.lock();
    if(!a)
    {
   
        cout << "a = " << a << endl;
        my_mutex.unlock();
        return false;
    }
    my_mutex.unlock();
    return true;    
}

注意上述代码在return前均调用了unlock

RAII std::lock_guard

C++标准库为互斥量提供了一个RAII语法的模板类std::lock_guard,其会在**构造的时候提供已锁的互斥量,并在析构的时候进行解锁**,从而保证了一个已锁的互斥量总是会被正确的解锁

mutex my_mutex;
int a = 1;
bool func()
{
      
    lock_guard<mutex> my_guard(my_mutex);
    // my_mutex.lock();
    if(!a)
    {
   
        cout << "a = " << a << endl;
        // my_mutex.unlock();
        return false;
    }
    // my_mutex.unlock();
    return true;    
}

可以通过限制lock_guard的作用域来提前释放锁

mutex my_mutex;
int a = 1;
bool func()
{
   
    // lock_guard<mutex> my_guard(my_mutex);
    // my_mutex.lock();
    if (!a)
    {
   
        {
   
            lock_guard<mutex> my_guard(my_mutex);
            cout << "a = " << a << endl;
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值