笔者在学习JUC包的时候,了解到同样用于线程阻塞和恢复功能的类—— LockSupport,那么这个类和Thread.suspend() 和 Thread.resume() 有什么区别,为什么后者被弃用了?
阻塞小例子
该例子(来源于Bug Database)很好的验证了Thread.suspend()/resume()这对兄弟天生容易犯错,在输出几个i之后就会发生永久性阻塞(通过jstack看,只能判断其是阻塞,无法判断是死锁)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/* ---------Thread.suspend 和 resume发生“死锁”的示例--------- */
public static void main(String[] args) throws InterruptedException {
TestTask mainThread = new TestTask();
mainThread.start();
while(true){
if(!mainThread.isTalking){
// LockSupport.unpark(mainThread);
mainThread.resume();
mainThread.isTalking = true;
}
}
}
static class TestTask extends Thread {
volatile boolean isTalking = true;
int i = 0;
public void run() {
while (true) {
if (isTalking) {
i++;
isTalking = false;
// LockSupport.park();
suspend();
System.out.println(i);
}
}
}
}
弃用原因
在这个方面,笔者上网了解过很多,许多人都是泛泛而谈,甚至是随手复制粘贴,质量低的可怕,完全无法了解到为什么它被弃用了。笔者最后在Bug Database上了解到了原因:
- Thread.suspend()和Thread.resume() 发生阻塞的原因主要在于底层JVM在暂停时候的不安全
- 就算花大力气修复了Thread.suspend()和Thread.resume(),问题也会转移到应用层级别(这一点暂时无法理解) 。
Thread.suspend() 和 Thread.resume() 被弃用的原因
有能力的朋友们可以直接看原文,可以一起交流一下看法。
替代方案
- Object.wait()和Object.notify()/notifyAll(),该方法需要在synchronized()中使用,极其麻烦
- LockSupport 粒度小,使用方便
小栗子
暂时没想法,后续补上