C++ std::Recursive_mutex 支持 “对同一互斥量进行嵌套加锁”

使用场景:一个类的不同成员函数之间,存在相互调用的情况, 如果这样的成员函数作为线程的入口函数时,就会出现在成员函数 func1()中对某个互斥量上锁,并且, func1()中调用了成员函数 func2() ,实际上 func2()为了保护成员数据,func2()内部也对同一个互斥量上锁。 在我们对 std::mutex 的使用经验中, 这样的情况,必定会导致未定义的行为,从而导致死锁的产生。

C++标准库为此提供了 std::recursive_mutex 互斥量, 它在具备 std::mutex 的功能之上, 还可以可以支持上面描述的 “对同一个互斥量进行嵌套上锁” 的能力。

注意:这个 “嵌套锁”的能力只是在同一线程中, 多个线程间还是保持与 std::mutex 一致的互斥同步能力。

下面分别贴出成员函数存在嵌套调用时 std::recursive_mutex 比 std::mutex 超强的表现能力。

1 #include
 2 #include
 3 #include
 4 #include
 5
 6 class Try_Recursive_Mutex
 7 {
 8     std::mutex   mtx;
 9     std::recursive_mutex recur_mtx;
10     std::chrono::milliseconds sleep_time = std::chrono::milliseconds(1000);
11 public:
12     Try_Recursive_Mutex();
13
14     void fun1(){
15         std::lock_guard lkgd( recur_mtx );
16         std::cout<"---thread id: "<"---"<<std::endl;
17         std::this_thread::sleep_for(sleep_time);
18         fun2();
19     }
20
21     void fun2(){
22         std::lock_guard lkgd( recur_mtx );
23         std::cout<"---thread id: "<"---"<<std::endl;
24         std::this_thread::sleep_for(sleep_time);
25         fun3();
26     }
27
28     void fun3(){
29         std::lock_guard lkgd( recur_mtx );
30         std::cout<"---thread id: "<"---"<<std::endl;
31         std::this_thread::sleep_for(sleep_time);
32     }
33 };
1 #include "Try_Recursive_Mutex.h"
 2 #include
 3
 4 int main()
 5 {
 6     Try_Recursive_Mutex trm;
 7     std::thread th_1(&Try_Recursive_Mutex::fun1, &trm);
 8     std::thread th_2(&Try_Recursive_Mutex::fun1, &trm);
 9     std::thread th_3(&Try_Recursive_Mutex::fun1, &trm);
10     th_1.join();
11     th_2.join();
12     th_3.join();
13     return 0;
14 }

运行结果如下:

16:24:34: Starting D:\a_zhm\StudyCode\threadStudy\14_protect_unNormalUpdate_data\build-protect_unNormalUpdate_data-Desktop_Qt_5_9_8_MSVC2015_64bit-Debug\debug\protect_unNormalUpdate_data.exe…

Try_Recursive_Mutex::fun1—thread id: 13484—

Try_Recursive_Mutex::fun2—thread id: 13484—

Try_Recursive_Mutex::fun3—thread id: 13484—

Try_Recursive_Mutex::fun1—thread id: 8224—

Try_Recursive_Mutex::fun2—thread id: 8224—

Try_Recursive_Mutex::fun3—thread id: 8224—

Try_Recursive_Mutex::fun1—thread id: 528—

Try_Recursive_Mutex::fun2—thread id: 528—

Try_Recursive_Mutex::fun3—thread id: 528—

16:24:43: D:/a_zhm/StudyCode/threadStudy/14_protect_unNormalUpdate_data/build-protect_unNormalUpdate_data-Desktop_Qt_5_9_8_MSVC2015_64bit-Debug/debug/protect_unNormalUpdate_data.exe exited with code 0

同样的情况,我们使用传统的 std::mutex 来实现,就会出现未定义行为,产生死锁而导致程序崩溃:

1 #include
 2 #include
 3 #include
 4 #include
 5
 6 class Try_Recursive_Mutex
 7 {
 8     std::mutex   mtx;
 9     std::recursive_mutex recur_mtx;
10     std::chrono::milliseconds sleep_time = std::chrono::milliseconds(1000);
11 public:
12     Try_Recursive_Mutex();
13
14     void fun1(){
15         std::lock_guard lkgd( mtx );
16         std::cout<"---thread id: "<"---"<<std::endl;
17         std::this_thread::sleep_for(sleep_time);
18         fun2();
19     }
20
21     void fun2(){
22         std::lock_guard lkgd( mtx );
23         std::cout<"---thread id: "<"---"<<std::endl;
24         std::this_thread::sleep_for(sleep_time);
25         fun3();
26     }
27
28     void fun3(){
29         std::lock_guard lkgd( mtx );
30         std::cout<"---thread id: "<"---"<<std::endl;
31         std::this_thread::sleep_for(sleep_time);
32     }
33 };

程序的运行情况如下:

C++ std::Recursive_mutex 支持 “对同一互斥量进行嵌套加锁”

总结: 新科技 std::recursive_mutex 就是好用!!! 特定场合,我们就选用特殊的技术。

Original: https://www.cnblogs.com/azbane/p/15814093.html
Author: 我是张洪铭我是熊博士
Title: C++ std::Recursive_mutex 支持 “对同一互斥量进行嵌套加锁”

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/535286/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • C++11 并发指南系列

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南三(std::mutex 详解)(本章计划 1-2 …

    C++ 2023年5月29日
    059
  • C++ 回调函数(CallBack)的用法分析

    本文实例分析了C++中回调函数(CallBack)的用法。分享给大家供大家参考。具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。其错误是…

    C++ 2023年5月29日
    047
  • C++ 回调函数详解

    1、什么是回调函数回调函数本质上也是普通函数,只是调用机制有所区别——首先通过传参的形式将该函数的地址传递给其他函数,然后在其他函数中通过函数指针调用该函数。在其他函数中通过函数指…

    C++ 2023年5月29日
    072
  • std::get<C++11多线程库~线程间共享数据>(10):使用互斥量保护共享数据(4)

    1 #ifndef DEADLOCK_QUESTIONDESCRIBLE_AND_SOLUTION_H 2 #define DEADLOCK_QUESTIONDESCRIBLE_A…

    C++ 2023年5月29日
    054
  • 选择排序 C++实现

    实现思想: 1.寻找[i, n)区间里的最小值min ( i>= 0 ) 2.交换min和第i的数 ( i>= 0 ) #include #include using …

    C++ 2023年5月29日
    058
  • (筆記) 如何寫入binary file某個byte的值? (C/C++) (C)

    Abstract通常公司為了保護其智慧財產權,會自己定義檔案格式,其header區會定義每個byte各代表某項資訊,所以常常需要直接對binary檔的某byte直接進行寫入。 In…

    C++ 2023年5月29日
    048
  • C++实现图的遍历和最短路径

    摘自:https://blog.csdn.net/qq_45694646/article/details/106764026 C++实现图的基本操作 数据结构之图(存储,遍历,最短…

    C++ 2023年5月29日
    069
  • C++经典案例

    per-thread的单例模式 //单例子模式,per-thread的单例模式 IPCThreadState* IPCThreadState::self() //IPCThread…

    C++ 2023年5月29日
    056
  • C/C++ 回调函数(Callback)& 函数指针

    摘要:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的…

    C++ 2023年5月29日
    053
  • c++类大四个默认函数-构造函数 析构函数 拷贝构造函数 赋值构造函数

    每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数)。对于任意一个类A,如果不编写上述函数,C++编译器将自动为A 产生四个缺…

    C++ 2023年5月29日
    060
  • js c++ 多值返回 返回多个值 c++ tuple

    使用C# 7.0推出的值元组和解构功能。 static (int, int) Calc(int a, int b) { return (a + b, a – b); } stati…

    C++ 2023年5月29日
    063
  • [转][c++11]我理解的右值引用、移动语义和完美转发

    c++中引入了 &#x53F3;&#x503C;&#x5F15;&#x7528;和 &#x79FB;&#x52A8;&#x8…

    C++ 2023年5月29日
    062
  • C++ 获取当前时间毫秒数

    在window环境下:1、精确到毫秒 include “stdafx.h” include include Original: https://www.cn…

    C++ 2023年5月29日
    052
  • VC++.net 整合开发环境使用技巧

    VC++.net 整合开发环境使用技巧 在下面我将会以条目的形式为大家描述VC.net2003的各项使用技巧,你完全可以挑选你感兴趣的内存来看,甚至不看都无所谓哈,只求你的一点支持…

    C++ 2023年5月29日
    057
  • (转)C/C++中计算程序运行时间

    以前经常听人提起如何计算程序运行时间,给出一系列函数,当时没有注意,随便选了clock()最简单的方式进行计算。等到真正需要检测程序性能提升了多少,才发现这里面有很多要注意的地方。…

    C++ 2023年5月29日
    055
  • Windows Runtime——-面向对象化的c++(并非意味着托管)

    Windows8的开发平台总体上分为两部分:一是全新的WinRT,界面搭配Metro style,二是传统的Win32、.NET(SL)、IE三大平台,界面为传统窗体风格。其中全新…

    C++ 2023年5月29日
    074
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球