前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++如何排查并发编程死锁问题?

C++如何排查并发编程死锁问题?

作者头像
公众号guangcity
发布2024-04-15 18:29:16
970
发布2024-04-15 18:29:16
举报
文章被收录于专栏:光城(guangcity)光城(guangcity)

C++如何排查并发编程死锁问题?

最近在Apache arrow里面写一个支持并行的算子:nested loop join,然后既然涉及到并行,这里就会遇到大家常说的死锁问题,假设你碰到了死锁问题,如何调试与定位呢?

那这便是本篇目标,帮助你快速掌握并发编程:死锁检测与死锁调试问题,非常的干,好了进行正文。

1.引入

为了更好的讲解死锁,我们用一个程序来引入。

代码语言:javascript
复制
std::mutex gMutex;

int t2() {
  std::lock_guard<std::mutex> m(gMutex);
  return 0;
}

int t1() {
  std::lock_guard<std::mutex> l(gMutex);
  return t2();
}

相信看这个程序,大家都会觉得有问题,死锁了!问题出在t1()函数和t2()函数中都对全局的互斥锁gMutex进行了加锁操作,但是t1()函数在加锁后调用了t2()函数,而t2()函数内部又试图再次对gMutex进行加锁。

t1锁已经加上了,但还没释放,t2又去加锁,两个人都在等待谁先释放,进入了死循环,实际在项目中代码并不会如这里这么简单,非常的复杂,例如:我在Apache arrow中写的代码是这样:

代码语言:javascript
复制
Status OnBuildSideFinished(size_t thread_index) {
  std::lock_guard<std::mutex> guard(probe_side_mutex_);
  // do something
  accumulate_build_ready_ = true;
  return scheduler_->StartTaskGroup(thread_index,task_group_probe_,queued_batches_to_probe_.batch_count()); 
}

你看这个代码比上面的场景就复杂多了,嵌套了至少5层堆栈,剩余代码还没贴出来,但是这两个本质都是一个死锁模型。

2.调试

讲解了死锁模型之后,碰到这种问题,如何定位呢?

这里可以采用两种办法,第一种直接运行程序,然后gdb上去。

例如:

代码语言:javascript
复制
./a.out

然后找到进程号后:

代码语言:javascript
复制
gdb -p xxx

此时我们可以得到及格正在等待的线程。

代码语言:javascript
复制
(gdb) info threads 
  Id   Target Id                                 Frame 
* 1    Thread 0x7ffff7fe2740 (LWP 32301) "a.out" 0x00007ffff7bc8017 in pthread_join () from /lib64/libpthread.so.0
  2    Thread 0x7ffff6fd0700 (LWP 32305) "a.out" 0x00007ffff7bcd54d in __lll_lock_wait () from /lib64/libpthread.so.0

然后去看__lll_lock_wait的堆栈,例如这里我看了2号线程,然后查看堆栈得到t1与t2的行号,直接可以定位到哪里出了问题,非常的直观!

除了这种方式之外,还可以直接gdb上去运行程序,此时会卡死,然后ctrl + c杀掉之后也是可以跟上面一样的内容。

例如:

代码语言:javascript
复制
(gdb) r
Starting program: /home/light/a.out 
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Hello World!
[New Thread 0x7ffff6fd0700 (LWP 32305)]
^C
Thread 1 "a.out" received signal SIGINT, Interrupt.
0x00007ffff7bc8017 in pthread_join () from /lib64/libpthread.so.0
Missing separate debuginfos, use: debuginfo-install libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
(gdb) info threads 
  Id   Target Id                                 Frame 
* 1    Thread 0x7ffff7fe2740 (LWP 32301) "a.out" 0x00007ffff7bc8017 in pthread_join () from /lib64/libpthread.so.0
  2    Thread 0x7ffff6fd0700 (LWP 32305) "a.out" 0x00007ffff7bcd54d in __lll_lock_wait () from /lib64/libpthread.so.0

好了,本节就讲这么多,感兴趣的欢迎转发这篇硬核文章!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++如何排查并发编程死锁问题?
  • 1.引入
  • 2.调试
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档