当前位置: 首页 > news >正文

C++的并发世界(七)——互斥锁

0.死锁的由来

假设有两个线程T1和T2,它们需要对两个互斥量mtx1和mtx2进行访问。而且需要按照以下顺序获取互斥量的所有权:
-T1先获取mte1的所有权,再获取mt2的所有权。
-T2先获取 mtx2的所有权。再铁取 mtx1的所有权。
如果两个线程同时执行,就会出现死锁问题。因为T1获取了mtx1的所有权,但是无法获取mtx2的所有权,而T2获取了mtx2的所有权,但是无法获取 mtx1的所有权,两个线程互相等待对方释放互斥量,导致死锁。

1.不同锁类型

类型类名作用
超时锁timed_mutex避免长时间死锁
递归锁recursive_mutex同一线程的同一锁可以锁多次避免死锁
共享锁shared_mutex可以充分利用cpu资源

2.各种锁

2.1超时锁

①作用:避免长时间死锁
②性质:可以记录锁获取情况,多次超时,可以记录日志,获取错误情况。

#include <iostream>
#include <thread>
#include <mutex>std::timed_mutex tmux;void ThreadMainTime(int i)
{for (;;){if (tmux.try_lock_for(std::chrono::microseconds(500))){std::cout << i << ":[try_lock_for timeout]" << std::endl;continue;}std::cout << "[in]"<< i << std::endl;tmux.unlock();std::this_thread::sleep_for(std::chrono::microseconds(1));}
}int main()
{for (int i = 0; i < 3; i++){std::thread th(ThreadMainTime, i + 1);th.detach();}getchar();return 0;
}

2.2递归锁

①作用:同一线程的同一锁可以锁多次,避免不必要的死锁。
②性质:组合业务用到同一个锁

注:recursive_timed_mutex为递归超时锁!

#include <iostream>
#include <thread>
#include <mutex>std::recursive_mutex rmux;void Task1()
{rmux.lock();std::cout << "task1 [in] " << std::endl;rmux.unlock();
}void Task2()
{rmux.lock();std::cout << "task2 [in] " << std::endl;rmux.unlock();
}void ThreadMainRec(int i)
{for (;;){rmux.lock();Task1();std::cout << i << "[in]" << std::endl;std::this_thread::sleep_for(std::chrono::microseconds(2000));Task2();rmux.unlock();}
}int main()
{for (int i = 0; i < 3; i++){std::thread th(ThreadMainRec, i + 1);th.detach();}getchar();return 0;
}

2.3共享锁

在这里插入图片描述

#include <iostream>
#include <thread>
#include <mutex>
#include <shared_mutex>std::shared_timed_mutex stmux;void ThreadRead(int i)
{for (;;){stmux.lock_shared();std::cout << "Read:" << i << std::endl;std::this_thread::sleep_for(std::chrono::microseconds(3000));stmux.unlock_shared();std::this_thread::sleep_for(std::chrono::microseconds(1));}
}void ThreadWrite(int i)
{for (;;){stmux.lock_shared();stmux.unlock_shared();stmux.lock();std::cout << "Write:" << i << std::endl;std::this_thread::sleep_for(std::chrono::microseconds(3000));stmux.unlock();std::this_thread::sleep_for(std::chrono::microseconds(1));}
}int main()
{for (int i = 0; i < 3; i++){std::thread th(ThreadWrite, i + 1);th.detach();}for (int i = 0; i < 3; i++){std::thread th(ThreadRead, i + 1);th.detach();}getchar();return 0;
}
http://www.lryc.cn/news/336682.html

相关文章:

  • NI-LabView的DAQ缺少或丢失的解决办法(亲测有效)
  • cesium 调整3dtiles的位置 世界坐标下 相对坐标下 平移矩阵
  • flutter跑通腾讯云直播Demo
  • 飞机降落蓝桥杯[2023蓝桥省赛B组]
  • 如何动态渲染HTML内容?用v-html!
  • EFcore 6 连接oracle19 WinForm vs2022
  • (delphi11最新学习资料) Object Pascal 学习笔记---第9章第2节(finally代码块)
  • 220 基于matlab的考虑直齿轮热弹耦合的动力学分析
  • Intrigue Core:一款功能强大的攻击面枚举引擎
  • 【精品PPT】智慧路灯大数据平台整体建设实施方案(免费下载)
  • idea 中运行spring boot 项目报 Command line is too long的解决办法。
  • Windows终端添加git bash
  • 【方法】PDF密码如何取消?
  • 怎么开发一个预约小程序_一键预约新体验
  • JavaScript_注释数据类型
  • 蓝桥杯2020年第十一届省赛 CC++ 研究生组2.0
  • SOCKS5代理、代理IP、跨界电商、游戏技术与网络安全的综合探讨
  • 关于HTTP1.0、1.1、1.x、2.0、3.0与HTTPS之间的理解
  • useRef总结
  • 计算机网络知识等汇总补充
  • word中插入mathtype版的符号后,行间距变大解决方法
  • 怎么给html文件本地启动一个服务去访问
  • LabVIEW无线快速存取记录器(WQAR)测试平台
  • 12-pyspark的RDD算子注意事项总结
  • 设备基础命令,路由基础
  • golang context
  • GPT中的Transformer架构以及Transformer 中的注意力机制
  • Hive的简单学习二
  • Qt事件处理机制3-事件函数的分发
  • 4月9号总结