c++ 递归锁的使用
非递归锁
同一个线程里,在锁未释放的情况下反复加锁,会导致死锁。
- 示例
#include <iostream>
#include <mutex>
#include <thread>
#include <unistd.h>
using namespace std;std::mutex m_mutex;void Func()
{m_mutex.lock();cout << "Func" << endl;m_mutex.unlock();
}int main()
{// create threadstd::thread th1 = std::thread([&]() {while(1){m_mutex.lock();cout << "thread1 working" << endl;Func();m_mutex.unlock();sleep(1);}});th1.join(); while(1){sleep(2);}return 0;
}
- 运行
[root@localhost ~]# ./testDeadLock
thread1 working
发现程序卡住不动,无Func函数中的打印。
- 调试
[root@localhost deadLock]# ps -aux | grep testDeadLock
root 88473 0.0 0.1 27200 1156 pts/1 Sl+ 14:13 0:00 ./testDeadLock
root 88541 0.0 0.1 112832 996 pts/2 R+ 14:13 0:00 grep --color=auto testDeadLock
[root@localhost deadLock]# gdb attach 88473
//...
(gdb) info threadsId Target Id Frame 2 Thread 0x7f13e4603700 (LWP 88474) "testDeadLock" 0x00007f13e530454d in __lll_lock_wait () from /lib64/libpthread.so.0
* 1 Thread 0x7f13e5a1d740 (LWP 88473) "testDeadLock" 0x00007f13e52ff017 in pthread_join () from /lib64/libpthread.so.0
(gdb) t 2
[Switching to thread 2 (Thread 0x7f13e4603700 (LWP 88474))]
#0 0x00007f13e530454d in __lll_lock_wait () from /lib64/libpthread.so.0
(gdb) bt
#0 0x00007f13e530454d in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f13e52ffe9b in _L_lock_883 () from /lib64/libpthread.so.0
#2 0x00007f13e52ffd68 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3 0x0000000000402534 in __gthread_mutex_lock (__mutex=0x604120 <m_mutex>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/x86_64-redhat-linux/bits/gthr-default.h:748
#4 0x0000000000402584 in std::mutex::lock (this=0x604120 <m_mutex>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_mutex.h:103
#5 0x0000000000401f88 in Func () at source/test.cpp:12
#6 0x000000000040200a in <lambda()>::operator()(void) const (__closure=0x2439018) at source/test.cpp:28
#7 0x0000000000402242 in std::__invoke_impl<void, main()::<lambda()> >(std::__invoke_other, <unknown type in /home/testDeadLock, CU 0x0, DIE 0xada9>) (__f=<unknown type in /home/testDeadLock, CU 0x0, DIE 0xada9>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/invoke.h:60
#8 0x000000000040209e in std::__invoke<main()::<lambda()> >(<unknown type in /mnt/hgfs/test/deadLock/debug.x64-linux-g8/testDeadLock, CU 0x0, DIE 0xb073>) (__fn=<unknown type in /home/testDeadLock, CU 0x0, DIE 0xb073>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/invoke.h:95
#9 0x0000000000402484 in std::thread::_Invoker<std::tuple<main()::<lambda()> > >::_M_invoke<0>(std::_Index_tuple<0>) (this=0x2439018) at /opt/rh/devtoolset-8/root/usr/include/c++/8/thread:244
#10 0x000000000040245a in std::thread::_Invoker<std::tuple<main()::<lambda()> > >::operator()(void) (this=0x2439018) at /opt/rh/devtoolset-8/root/usr/include/c++/8/thread:253
#11 0x000000000040243e in std::thread::_State_impl<std::thread::_Invoker<std::tuple<main()::<lambda()> > > >::_M_run(void) (this=0x2439010) at /opt/rh/devtoolset-8/root/usr/include/c++/8/thread:196
#12 0x00000000004028ff in execute_native_thread_routine ()
#13 0x00007f13e52fdea5 in start_thread () from /lib64/libpthread.so.0
#14 0x00007f13e4702b0d in clone () from /lib64/libc.so.6
(gdb) f 5
#5 0x0000000000401f88 in Func () at source/test.cpp:12
12 m_mutex.lock();
(gdb) p *(pthread_mutex_t*)$rdi
$1 = {__data = {__lock = 2, __count = 0, __owner = 88474, __nusers = 1, __kind = 0, __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}}, __size = "\002\000\000\000\000\000\000\000\232Y\001\000\001", '\000' <repeats 26 times>, __align = 2}
(gdb)
- 排查步骤
1) ps查看进程id;2) "gdb attach 进程id"附加至该进程;3) "info threads"查看所有线程信息;4) 查找有执行锁等待__lll_lock_wait ()的线程, 一般为死锁线程, 切换至该线程, 如切换至线程2,则执行"t 2";5) "bt" 查看当前线程堆栈;6) "f 帧数"切换至自己所写代码处;7) "p *(pthread_mutex_t*)$rdi"打印寄存器信息, rdi为显示寄存器;8) 对7)的打印主要关注两个地方,"__lock = 2"一般说明有死锁, "__owner = 88474"代码发生死锁的线程, 与"info threads"的打印信息中 "(LWP 88474)"对应, 接下来直接分析88474指向的线程即可;
此排查方式适用于多个线程出现死锁的情况。
递归锁
递归锁允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作。
- 示例
在c++11中,std::recursive_mutex 来支持递归锁。
#include <iostream>
#include <mutex>
#include <thread>
#include <unistd.h>
using namespace std;std::recursive_mutex m_recursive_mutex;void Func()
{std::lock_guard<std::recursive_mutex> mtx(m_recursive_mutex);cout << "Func" << endl;
}int main()
{// create thread1std::thread th1 = std::thread([&]() {while(1){std::lock_guard<std::recursive_mutex> mtx(m_recursive_mutex);cout << "thread1 working" << endl;Func();sleep(1);}});th1.join(); while(1){sleep(2);}return 0;
}
- 运行
[root@localhost ~]# ./testDeadLock
thread1 working
Func
thread1 working
Func
thread1 working
Func
thread1 working
Func
程序可正常打印。
windows下递归锁
- 特点
- windows下的互斥量和临界区(关键段)默认支持递归锁;
- EnterCriticalSection可以被多次调用;
- EnterCriticalSection与LeaveCriticalSection调用次数必须对应;
- 临界区函数如下:
// 初始化一个临界区对象
void InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection);// 删除临界区对象释放由该对象使用的所有系统资源
void DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);// 进入临界区
void EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );// 删除临界区
void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
- 示例
#include <iostream>
#include <thread>
#include <Windows.h>
using namespace std;CRITICAL_SECTION g_Critical;class CWinRecursiveLock
{
public:CWinRecursiveLock(CRITICAL_SECTION *pCritcal) {m_pCritical = pCritcal;EnterCriticalSection(m_pCritical);}~CWinRecursiveLock() //析构函数{LeaveCriticalSection(m_pCritical);}private:CRITICAL_SECTION *m_pCritical = nullptr;
};void Func()
{CWinRecursiveLock wlock(&g_Critical); // 重复加锁cout << "Func" << endl;
}int main()
{// 初始化InitializeCriticalSection(&g_Critical);std::thread th1 = std::thread([&]() {while(1){CWinRecursiveLock wlock(&g_Critical);cout << "thread1 working" << endl;Func();Sleep(1000);}});th1.join(); system("pause");return 0;
}
经测试,程序可正常运行。
相关文章:
c++ 递归锁的使用
非递归锁 同一个线程里,在锁未释放的情况下反复加锁,会导致死锁。 示例 #include <iostream> #include <mutex> #include <thread> #include <unistd.h> using namespace std;std::mutex m_mutex;void Func() {m_mutex.lock(…...
Oracle TDE wallet
1. 钱夹密码千万不能忘记,这也是使用TDE 需要承担的风险。 2. 只要将wallet cwallet.sso 拷贝过去,加密没有意义! 钱夹的备份 正如上述,已经加密过的表列或者表空间,钱夹必须打开才能够查询到里面的数据。如果钱夹丢…...
多模态学习
一、目标 三、多模态核心任务 题目:...
Android学习之路(2) 文本设置
Android学习之路(1) 文本 一、设置文本内容 设置文本内容的两种方式: 一种是在XML文件中通过属性android:text设置文本代码如下 <TextViewandroid:id"id/tv_hello"android:layout_width"wrap_content"android:layout_height"wrap_c…...
手写springboot
前言 首先确定springboot在spring基础上主要做了哪些改动:内嵌tomcatspi技术动态加载 一、基本实现 1. 建一个工程目录结构如下: springboot: 源码实现逻辑 user : 业务系统2.springboot工程项目构建 1. pom依赖如下 <dependencies>…...
报错Uncaught (in promise) Error: Manifest request to...
在使用nuxt框架时,出现如下报错: 解决方案: 不要打开两个以上的开发者工具更换nuxt的端口号 参考资料:https://github.com/nuxt/nuxt.js/issues/6202...
微信私域更好玩了
之前分享过,“小绿书”“公众号文章转音频”等内测中或悄悄已升级的功能。 其实,微信还在内测很多新功能,只是没公开 今天,小编又发现新升级 就是『附近』功能 增加了一个本地生活的入口,这里面是短视频和图文 展示…...
基于ant-design的a-modal自定义vue拖拽指令
写一个dragDialog.js 在main.js中引入 import ‘./core/directives/dragDialog.js’ // 让 dialog 支持鼠标拖动 import Vue from vueVue.directive(DragDialog, {update: function (el, binding, vnode) {if (!binding.value || !binding.value.reset) returnconst dialog e…...
【ES】笔记-模板字符串(template string)是增强版的字符串`${expresions}`
模板字符串 传统的 JavaScript 语言,输出模板通常是这样写的(下面使用了 jQuery 的方法)。 $(#result).append(There are <b> basket.count </b> items in your basket, <em> basket.onSale </em> are on sal…...
利用 OLE 对象漏洞的 HWP 恶意文件浮出水面
ASEC 分析人员发现了一个利用 OLE 对象的恶意 HWP 文件,尽管其使用了 2020 年就被识别的恶意 URL,但仍然使用了 Flash 漏洞(CVE-2018-15982),需要用户谨慎对待。 打开 HWP 文件时会在 %TEMP%文件夹中生成如下文件。攻…...
【CSS】倾斜按钮
效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"/><meta http-equiv"X-UA-Compatible" content"IEedge"/><meta name"viewport" content"widthdevice-…...
js 正则表达式
js 正则表达式 http://tool.oschina.net/regex https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions 11 22...
心理咨询预约管理系统javaweb医院挂号jsp源代码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 心理咨询预约管理系统javaweb MVC模式,普…...
Linux中安装Node
安装 先从 官方网站 下载安装包,有时 node 版本太新会导致失败,详见下方的常见问题第2点 cd /home // 创建目录,将下载好的 node 安装包上传到此目录 mkdir Download mkdir /usr/local/lib/node解压 // 解压,前面是文件当前路径…...
爬虫011_元组高级操作_以及字符串的切片操作---python工作笔记030
获取元组的下标对应的值 注意元组是不可以修改值的,只能获取不能修改 但是列表是可以修改值的对吧...
JVM虚拟机篇
JVM组成 面试题1:什么是程序计数器? 面试题2:你能给我详细的介绍Java堆吗? 面试题3:什么是虚拟机栈? 面试题4:垃圾回收是否涉及栈内存? 垃圾回收主要指就是堆内存,当栈帧弹栈以后…...
Flutter 让软键盘不再自动弹起
1、问题说明: 在开发中,经常遇到这种事,一个页面有输入框,点击输入框后,会弹起软键盘,同时输入框会聚焦,手动收起软键盘后,点击另一个按钮前往下一个页面或者显示一个弹窗࿰…...
k8s 自身原理 1
咱们从 pod 一直分享到最近的 Statefulset 资源,到现在好像我们只是知道如何使用 k8s,如何按照 k8s 设计好的规则去应用,去玩 k8s 仔细想想,对于 k8s 自身的内在原理,我们好像还不是很清楚,对于每一个资源…...
在CPU上安装部署chatglm-6b实用经验分享
chatglm-6b很强,很多同学都想自己试一试,但不是每个人都有GPU、高端显卡的环境,大多数同学都是一台普通的笔记本。 笔者这里分享一下在自己的8G内存,intel i3笔记本上安装部署chatglm-6b的实际经验。有很多网站都分享了一些经验&…...
Mermaid系列之FlowChart流程图
一.欢迎来到我的酒馆 介绍mermaid下,Flowchat流程图语法。 目录 一.欢迎来到我的酒馆二.什么是mermiad工具三.在vs code中使用mermaid四.基本语法 二.什么是mermiad工具 2.1 mermaid可以让你使用代码来创建图表和可视化效果。mermaid是一款基于javascript语言的图表…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
