菜鸟笔记
提升您的技术认知

一个死锁问题分析-ag真人游戏

源程序来源于github:recipes/factory_deadlock.cc at master · chenshuo/recipes (github.com)

加了编译选项reproduce_bug后会导致死锁,为什么会死锁呢?

这个程序一开始没有看懂,主要是有个知识点自己忽略了:

对象的析构是同步的,当最后一个指向xshared_ptr离开其作用域的时候,x会同时在同一个线程析构。这个线程不一定是对象诞生的线程。

主要过程为:

  1. main线程创建了一个stock对象叫ms,该对象地址为0x56354caa90c0
  2. 由于该对象的引用计数为0,于是立即调用定制的析构函数deletestock
  3. 主线程在deletestock中会休眠500毫秒,此时thrb线程创建了一个stock对象也叫ms,该对象地址为0x7f3020000b20,这个对象覆盖了之前main线程创建的对象在哈希表中的位置。
  4. main线程从休眠中醒来,继续执行,发现此时指向thrb线程创建的stock对象的引用计数值为2。
  5. main线程再次休眠500毫秒。
  6. thrb线程执行结束,发现其创建的stock对象的引用计数值为1(在main线程中),所以该对象不会在thrb中析构。
  7. main线程从休眠中唤醒,发现此时指向thrb线程创建的stock对象【0x7f3020000b20】的引用计数值为1。离开作用域后,引用计数为0,这个对象要在main线程中被析构。
  8. main线程里面再次调用定制的析构函数deletestock,于是导致死锁。
main: stock[0x56354caa90c0] ms
main: stock 0x56354caa90c0
main: deletestock[0x56354caa90c0]
thrb: stock[0x7f3020000b20] ms
thrb: stockb 0x7f3020000b20
use_count = 2
thrb: stockb destructs
use_count = 1
main: deletestock[0x7f3020000b20]
warning: mutex_ is already locked by this thread, deadlock will happen.

如果没有互斥锁的话,结果会这样:

main: stock[0x55c6ae0d40c0] ms
main: stock 0x55c6ae0d40c0
main: deletestock[0x55c6ae0d40c0]
thrb: stock[0x7fa980000b20] ms
thrb: stockb 0x7fa980000b20
use_count = 2
thrb: stockb destructs
use_count = 1
main: deletestock[0x7fa980000b20]
main: ~stock[0x7fa980000b20] ms
main: ~stock[0x55c6ae0d40c0] ms
main :~thread
网站地图