要以相同顺序获取多个锁

多线程在加锁解锁时,可能会出现死锁问题,比如,

线程 1 在加锁 mutex A 后,继续尝试获取 mutex B,而 mutex B 已经被线程 2 获取,而线程 2 在等待获取 mutex A,mutex B 只有线程 2 获取 mutex  A 后才能解锁,

这就导致线程 1 和线程 2 互相等待锁,而这一操作就是死锁情况,容易导致程序挂起。

使用代码模拟死锁场景:

#include <iostream>
#include <string>
#include <thread>
#include <mutex> using namespace std; std::mutex muA;
std::mutex muB; void CallHome_AB(string message)
{
muA.lock();
//Some additional processing
std::this_thread::sleep_for(std::chrono::milliseconds(100));
muB.lock(); cout << "Thread " << this_thread::get_id() << " says " << message << endl; muB.unlock();
muA.unlock();
} void CallHome_BA(string message)
{
muB.lock();
//Some additional processing
std::this_thread::sleep_for(std::chrono::milliseconds(100));
muA.lock(); cout << "Thread " << this_thread::get_id() << " says " << message << endl; muA.unlock();
muB.unlock();
} int main()
{
thread t1(CallHome_AB, "Hello from Jupiter");
thread t2(CallHome_BA, "Hello from Pluto"); t1.join();
t2.join(); return 0;
}  

运行后,会发现控制台没有打印任何字符串,因为两个线程都尝试获取对方的锁,导致了死锁

如何解决?

最好的办法就是所有的锁都可以以相同的顺序获得,比如线程 1 顺序获得 mutex A 和 mutex B,再释放 mutex B 和 mutex A,线程 2 也顺序获得 mutex A 和 B,再顺序释放

std::mutex muA;
std::mutex muB; void CallHome_AB(string message) {
muA.lock();
// Some additional processing
std::this_thread::sleep_for(std::chrono::milliseconds(100));
muB.lock(); cout << "Thread " << this_thread::get_id() << " says " << message << endl; muB.unlock();
muA.unlock();
} void CallHome_BA(string message) {
muA.lock();
// Some additional processing
std::this_thread::sleep_for(std::chrono::milliseconds(100));
muB.lock(); cout << "Thread " << this_thread::get_id() << " says " << message << endl; muB.unlock();
muA.unlock();
}

当然目前也有封装好的 C++ 函数来同时获得两个锁,如下

std::scoped_lock lock{muA, muB};

The class scoped_lockis a mutex wrapper that provides a convenient RAII-style mechanism for owning one or more mutexes for the duration of a scoped block.

When a scoped_lock object is created, it attempts to take ownership of the mutexes it is given. When control leaves the scope in which the scoped_lock object was created, the scoped_lock is destructed and the mutexes are released. If several mutexes are given, deadlock avoidance algorithm is used as if by std::lock.

或者我们也可以用 std::timed_mutex 来解决这个问题,当超过一定时间后自动释放锁

The timed_mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads.

C++ 多线程的错误和如何避免(7)的更多相关文章

  1. c++多线程崩溃错误1

    主线程中的子线程没有jion,导致主线程马上结束,子线程对象被释放掉,而子线程还在后台继续执行导致崩溃 int main() OBJ = classA() OBJ.START()//在start函数中 ...

  2. Java SE之快速失败(Fast-Fail)与快速安全(Fast-Safe)的区别[集合与多线程/增强For](彻底详解)

    声明 特点:基于JDK源码进行分析. 研究费时费力,如需转载或摘要,请显著处注明出处,以尊重劳动研究成果:博客园 - https://www.cnblogs.com/johnnyzen/p/10547 ...

  3. Java多线程知识总结(一)

    一.创建线程的三种方式: 创建线程的方式有三种,一是创建Thread实例,二是实现Runnable接口,三是实现Callable接口,Runnable接口和Callable接口的区别是一个无返回值,一 ...

  4. Java回顾之多线程同步

    在这篇文章里,我们关注线程同步的话题.这是比多线程更复杂,稍不留意,我们就会“掉到坑里”,而且和单线程程序不同,多线程的错误是否每次都出现,也是不固定的,这给调试也带来了很大的挑战. 在这篇文章里,我 ...

  5. 2019年北航OO第二单元(多线程电梯任务)总结

    一.三次作业总结 1. 说在前面 对于这次的这三次电梯作业,我采用了和几乎所有人都不同的架构:将每个人当作一个线程.这样做有一定的好处:它使得整个问题的建模更加自然,并且在后期人员调度变得复杂时,可以 ...

  6. 转:最近5年133个Java面试问题列表

    最近5年133个Java面试问题列表 Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试,但是现在问题变得越来 ...

  7. [转载]hashmap hashtable 的区别

    Hashtable 和 HashMap 做为 Map 的基本特性 两者都实现了Map接口,基本特性相同 -          对同一个Key,只会有一个对应的value值存在 -          如 ...

  8. Java笔试题解答和部分面试题

    面试类  银行类的问题 问题一:在多线程环境中使用HashMap会有什么问题?在什么情况下使用get()方法会产生无限循环? HashMap本身没有什么问题,有没有问题取决于你是如何使用它的.比如,你 ...

  9. Java 集合系列 11 hashmap 和 hashtable 的区别

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  10. 面试题_76_to_81_Java 最佳实践的面试问题

    包含 Java 中各个部分的最佳实践,如集合,字符串,IO,多线程,错误和异常处理,设计模式等等. 76)Java 中,编写多线程程序的时候你会遵循哪些最佳实践?(答案)这是我在写Java 并发程序的 ...

随机推荐

  1. [转帖]ARM内核全解析,从ARM7,ARM9到Cortex-A7,A8,A9,A12,A15到Cortex-A53,A57

    https://www.cnblogs.com/senior-engineer/p/8668723.html 前不久ARM正式宣布推出新款ARMv8架构的Cortex-A50处理器系列产品,以此来扩大 ...

  2. [转帖]win10多网卡指定ip走某个网卡的方案

    https://zhuanlan.zhihu.com/p/571614314 我的电脑上有两个网卡,一个网卡A(网线),一个是网卡B(WIFI). 需求:网卡A和网卡B是不同的网络,网卡A已经把338 ...

  3. [转帖]Redis中的Lua脚本

    最近琢磨分布式锁时接触到的知识点,简单记一下. 文章目录 1. Redis中的Lua 2. 利用Lua操作Redis 3. Lua脚本的原子性 4. 关于 EVALSHA 5. 常用`SCRIPT` ...

  4. 【转帖】SRE 高延迟问题的罪魁祸首 System.gc()

    https://www.infoq.cn/article/lXTRgYb9ecVBu*72fT7O jstact -gccause pid 3000 30 01 案例一: 某日,支付平台的开发人员找到 ...

  5. 【转帖】使用 LuaRocks 安装 Apache APISIX 依赖项时,为什么会导致超时、安装缓慢或安装失败?

    使用 LuaRocks 安装 Apache APISIX 依赖项时,为什么会导致超时.安装缓慢或安装失败?# http://apisix.incubator.apache.org/zh/docs/ap ...

  6. [转帖]NOHZ = ON如何影响Linux内核中的do_timer()?

    https://www.jb51.cc/faq/897483.html 如何解决NOHZ = ON如何影响Linux内核中的do_timer()?? 首先,让我们了解什么是tickless kerne ...

  7. [转帖]写给想了解"集成电路"的朋友

    https://zhuanlan.zhihu.com/p/602627000 寒假和朋友小聚,每当就专业问题展开谈话,很容易形成"一边热火朝天,一边大脑宕机"的局面.俗话说隔行如隔 ...

  8. 学习: Linux的 date 命令

    date 命令非常好用 多用 date --h 还是非常好的 获取 今天是今年的第多少天 最简单的办法 就是 date +%j 以后需要多学习 多利用 linux的帮助才可以呢. Usage: dat ...

  9. 分布式ID介绍&实现方案总结

    分布式 ID 介绍 什么是 ID? 日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品,订单 ID 对应且仅对应一个订单. ...

  10. JVM(Java虚拟机) 整理

    JVM整体结构 本文主要说的是HotSpot虚拟机, JVM 全称是 Java Virtual Machine,中文译名:Java虚拟机 简化一下: Java字节码文件 Class文件本质上是一个以8 ...