zoukankan      html  css  js  c++  java
  • 记一次dump文件定位锁

    行情报价关闭K线界面卡死

    前奏

    1. Dump收集
    2. Clr运行时文件收集
    3. 收集文件放到同一目录,VS打开
    4. 查看线程堆栈

    问题还原

    1. 主线程停在Messenger.UnregsiterCore处(关闭K线界面,调用VM的CleanUp方法引起)
    2. 工作线程1停在Messenger.Send处
    3. 工作线程2停在Forms.Control.WaitForWaitHandle处(堆栈上游是Messenger.Send后执行注册的方法)

    问题分析

    1. 上面的工作线程2的堆栈是一个常见的客户端死锁现象,一般由Control.Invoke调用,等待主线程操作权限
    2. 接下来看主线程现在在干什么,主线程在执行Messenger的取消注册方法
    3. 工作线程1也在执行Messenger的发送方法
    4. 查看Messenger源码,发现里面只有私有变量isMultiThreadSafe为true时,才会进入锁对象actionInvoker,而一般的Messenger.Default实例的该变量值为false
    5. 通过定位,Messenger.Default是我们自己赋的值,同时传参true,即isMultiThreadSafe=true
    6. 问题原因昭然若揭,工作线程2通过Send方法获取了锁actionInvoker,并执行Send事件对应的方法,方法内部调用Control.Invoke等待主线程回应。但此时主线程正在CleanUpK线的vm,同时取消Messenger的订阅,这个取消订阅需要等待锁actionInvoker被释放。这个锁actionInvoker被工作线程2占用,线程2在等主线程,主线程在等锁actionInvoker……死锁。

    解决方法

    1. 工作线程2的Control.Invoke调用,换成Control.BeginInvoke
    2. Messenger.Send方法是同步执行被注册方法的,导致方法没有执行完成时,锁一直被占用。我们可以添加一个IMessenger的Post扩展方法,在线程池上执行被注册方法,同时锁被立即释放,死锁环也可以解开。

    注:以上的Messenger为DevExpress的一个消息类

    转载请注明出处
  • 相关阅读:
    转载:PHP JSON_ENCODE 不编码中文汉字的方法
    【TP3.2】:日志记录和查看
    PHP原生:分享一个轻量级的缓存类=>cache.php
    python: 基本的日期与时间转换
    python: 随机选择
    计算机bit是什么意思
    Python: 矩阵与线性代数运算
    Python numpy 安装以及处理报错 is not a supported wheel on this platform
    Python: 大型数组运算
    Python numpy有什么用?
  • 原文地址:https://www.cnblogs.com/godlessspirit/p/14379637.html
Copyright © 2011-2022 走看看