首页 > 编程语言 >c++多线程同步

c++多线程同步

时间:2023-08-01 13:34:35浏览次数:39  
标签:std lockB 同步 lock c++ guard lockA mutex 多线程

死锁问题1

单核实时可抢占的系统中,优先级不同的三个线程A/B/C, A>B>C

  • 当C先获得时间片开始执行,并获得锁
  • A因为高优先级,被唤醒并中断C,但没有得到锁,而阻塞
  • B获得执行机会,由于优先级高于C,B会一直执行,让AC系统无法取得任何进展
std::stack<T> stack;
std::mutex mutex;

void push(const T& obj) {
   mutex.lock();
   stack.push(obj);
   mutex.unlock();
}

image

死锁问题2

  • 多个锁共同控制临界区
  • 加锁顺序不一致
  • A,B锁被两个线程分别持有,等待对方释放剩下的锁,不会主动释放所持有的锁,而导致死锁
#include <mutex>
#include <iostream>
#include <thread>
using namespace std;

mutex lockA;
mutex lockB;
int counter{0};

void foo() {
    while(true) {
        lock_guard<mutex> guardA(lockA);
        lock_guard<mutex> guardB(lockB);
        cout << "message from foo " << counter++ << endl;
    }
}

void bar() {
    while(true) {
        lock_guard<mutex> guardB(lockB); // 注意这里加锁顺序
        lock_guard<mutex> guardA(lockA);
        cout << "message from bar " << counter++ << endl;
    }
}

void DeadLockTest() {
    thread tf(foo);
    thread tb(bar);
    tf.join();
    tb.join();
}

解决多个锁导致死锁问题

  • 尽量只用一个锁
  • 如果必须用多个锁,注意顺序上锁
  • 无法保证上锁顺序的话,使用std::lock
void foo() {
    while(true) {
        std::lock(lockA, lockB);
        lock_guard<mutex> guardA(lockA, std::adopt_lock);
        lock_guard<mutex> guardB(lockB, std::adopt_lock);
        cout << "message from foo " << counter++ << endl;
    }
}

void bar() {
    while(true) {
        std::lock(lockB, lockA);
        lock_guard<mutex> guardB(lockB, std::adopt_lock); // 注意这里加锁顺序
        lock_guard<mutex> guardA(lockA, std::adopt_lock);
        cout << "message from bar " << counter++ << endl;
    }
}

参考

https://en.cppreference.com/w/cpp/thread/lock
http://en.cppreference.com/w/cpp/thread/lock_guard

标签:std,lockB,同步,lock,c++,guard,lockA,mutex,多线程
From: https://www.cnblogs.com/BuzzWeek/p/17594684.html

相关文章

  • RichEdit RTF格式文本的存储和读取 VC++
    Rtf格式文本的读写,向控件发送EM_STREAMIN和EM_STREAMOUT消息,控件把格式文本显示或从把显示内容转化为格式文本。接口是用户定义的回调函数,格式文本由参数DWORD_PTRdwCookie传递。从控件读出RTF文本,参数用string比较好,因为消息处理是根据文本的长度,多次调用回调函数,传出数......
  • java-多线程并发,CompletableFuture
    //无返回值@OverridepublicvoidexecCreateYmDetDataSubTask(YmDetCreateWorkerDtoymDetCreateWorkerDto){List<Long>sendIdList=ymDetCreateWorkerDto.getSendIdList();List<List<Long>>subLists=Lists.partition(sendIdList,1......
  • C++ Primer 第五版
    当我们使用istream对象作为条件时,其效果是检测流的状态.char:[-128,127].C++17新增byte数据类型,在<cstddef>头文件中定义,取值范围:[0,255].int和long都占用4字节空间.切勿混用带符号类型和无符号类型.\后跟3位以内8进制数字,或\x后跟一个或多个16进制数字都可以代表字符......
  • 【暑假例题】20230727 矩阵基本运算(C++)
    题目请使用C++实现矩阵的各种运算矩阵创建矩阵相加矩阵相减矩阵相乘数字乘矩阵矩阵上叠加矩阵左右叠加矩阵转置矩阵旋转矩阵求逆矩阵输出题目分析矩阵创建这里只需注意由于我们需要通过不同的函数对数组进行操作,所以我们需要将数组存储在容器或者使用指针防止数......
  • 音乐播放器实现歌词同步
    项目中音乐播放器实现歌词同步思路:1.读取LRC歌词文件信息2.将歌词时间段和对应时间段歌词保存至两个数组中,3.按时间顺序对两个数组进行排序核心代码如下:publicclassSongWord{publicString[]time;publicString[]songWord;publiclong[]songTime;privateUICon......
  • Java面试题 P19:Redis篇:Redis做为缓存,mysql的数据如何与redis进行同步呢(双写一致)
    双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致。     共享锁:读锁代码 排他锁,写数据。读锁和写锁的值要一致。   MQ异步消息通知:    ......
  • C++中不支持strdup(),使用_strdup()
    1.问题C4996 'strdup':ThePOSIXnameforthisitemisdeprecated.Instead,usetheISOCandC++conformantname:_strdup.Seeonlinehelpfordetails. Project1 G:\VS\Project1\Project1\MyString.cpp 802.原因错误C4996是一个编译器警告,它指示在代码中使用了一个......
  • c++11 call_once & once_flag
    #include<iostream>#include<mutex>usingnamespacestd;voidonce_fun(std::once_flag&&flag){std::call_once(flag,[](){cout<<"messagefromoncefun"<<endl;});}voidonce_fun1(s......
  • c++并发
    《c++并发编程第二版》,一方面翻译的挺拗口,一方面内容有点难度,看的很吃力,尤其到后面内存模型,无锁编程部分,看不下去了,仅记录部分内容。并发:采用任务切换的方式,一个任务运行一会在切换回另一个任务,在一个时间段内好像两个任务在同时进行并行:在多个CPU或多核CPU中同一时间多个任务同......
  • boost asio多线程模式-IOThreadPool
    今天给大家介绍asio多线程模式的第二种,之前我们介绍了IOServicePool的方式,一个IOServicePool开启n个线程和n个iocontext,每个线程内独立运行iocontext,各个iocontext监听各自绑定的socket是否就绪,如果就绪就在各自线程里触发回调函数。为避免线程安全问题,我们将网络数据封装为逻辑......