分享一个死锁案例

2017-07-30 00:48:00 +08:00
 RLib
UI 线程在等待线程池完成销毁, 但是线程池里的线程又给 UI 线程 POST 了消息(不是 APC),于是挂了,总结来讲,尽量不要让 UI 线程去做任何可能的等待
3019 次点击
所在节点    程序员
10 条回复
RLib
2017-07-30 00:49:29 +08:00
这里的 POST 表述不准确,应该是 SEND
yangff
2017-07-30 01:06:52 +08:00
嗯……
一个稍微比较坑一点的情节是这样的(
比如 UI 线程接到某个 event,去尝试销毁另一个线程持有的对象(通过线程间通讯去要求对方销毁),而那个线程是这个 event 实际上的发起者…… 于是他在等待 eventhandler 结束……

最关键的是,你在用 await + async 写这些代码的时候无比畅快……

比如 label1.Text = await DoCompution()之类的……

实际上都多多少少有些问题(
limhiaoing
2017-07-30 21:50:49 +08:00
@yangff
``` cs
label1.Text = await DoCompution();
```
DoCompution 实现正确的情况下会有问题?
yangff
2017-07-30 22:06:01 +08:00
@limhiaoing 正确情况下是不会有问题的……

然而你可能会再在里面写上一些看起来没问题的代码(或者你调用了一些库的实现有一些问题),导致整个东西 boom 掉……

而且这些东西可能不是很可以预计…… 毕竟有可能有的库就是二进制分发的…… 连源代码都没有
limhiaoing
2017-07-30 22:08:40 +08:00
@yangff
举个具体的例子看下呢?
limhiaoing
2017-07-30 22:11:20 +08:00
@yangff
指的是看起来没问题的代码。
yangff
2017-07-30 22:32:59 +08:00
@limhiaoing 不是很好举例子…… 一下想不起来之前出的问题了…… 大概的问题是出在
DoCompution 这里面调用了 DLL,这个 DLL 本身有一些问题会导致计算的这个线程等待一个 UI 线程那边的锁……

反正只用 await/async 应该是安全的
yangff
2017-07-30 22:34:55 +08:00
抽象一点说的话就是这样的,不过直接这样看其实感觉问题是很明显啦……

UIThread:
1. Lock
2. await (hold lock)

Computation Thread:
1. Lock
2. deadlock..
RLib
2017-07-31 16:56:02 +08:00
@limhiaoing 旁观者清当局者迷,大概说的就是这个,这你让别人怎么给你举例呢...
在解决完一个 bug 我们基本都会有个小结,但其实回顾来看,很少 bug 是超出认知范围的...
geelaw
2017-08-03 03:10:38 +08:00
一个很矛盾的事情:如果你的 UI 线程等待一个线程池,那么你的 UI 已经卡了,这已经很糟糕了。

正确的异步是让线程池完成销毁的最后步骤为通知 UI 线程自己搞定了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/378931

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX