
我今天参加了InteliJ并模拟了一个僵局.
由synced关键字修改的方法可能会导致死锁. (同步只能修改方法,就像volatile只能修改变量一样. )
简单介绍. 出现以下死锁的原因是,A线程需要获取lock1和lock2以便分别打印句子,而B线程需要获取lock2和lock1以便分别打印句子. 这两个线程是异步的. 在执行过程中,有两种情况:

方案1:
一个快速保持的锁1,保持的锁2,释放的锁2,释放的锁1,并成功打印了两个句子.
然后B按住lock2,按住lock1,释放lock1,释放lock2,并成功打印两个句子.
情况2:
A持有lock1并打印第一句(不释放lock1),这时B持有lock2并打印第一句;那么A想要持有lock2并等待B释放lock2,但是lock2无法释放,因为如果要释放lock2,则它必须首先获取lock1并执行任务.
请注意,这两个锁必须嵌套并调用.

看代码更容易理解:
public class TestDeadLock {
public void run() {
MyThread mt = new MyThread();
new Thread(mt, "张三").start();
new Thread(mt, "李四").start();
}
class MyThread implements Runnable {
//lock要写成final的,否则如果lock指向变了,锁就失效了
private final Object mLock1 = new Object();
private final Object mLock2 = new Object();
//boolean用来确保两个线程获得不同的锁。
private boolean flag = true;
@Override
public void run() {
if (flag) {
flag = false;
//注意,两把锁一要嵌套调用
synchronized (mLock1) {
System.out.println(Thread.currentThread().getName() + " have mLock1");
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
synchronized (mLock2) {
System.out.println(Thread.currentThread().getName() + " have mLock2");
}
}
} else {
flag = true;
synchronized (mLock2) {
System.out.println(Thread.currentThread().getName() + " have mLock2");
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
synchronized (mLock1) {
System.out.println(Thread.currentThread().getName() + " have mLock1");
}
}
}
}
}
public static void main(String[] args) {
new TestDeadLock().run();
}
}
我删除了睡眠部分,因此由于线程抢占了CPU资源,因此每次执行的结果将有所不同(上述两种情况).

下面的屏幕快照对应第一种情况:
image.png
下面的屏幕截图对应于第二种情况. 它被卡在这里死锁举例,并发生了死锁:
image.png
然后死锁举例,如果您放弃睡眠注释,就会发生第二种情况.
参考:
©版权归作者所有,如需转载或内容合作,请联系作者
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-237260-1.html
图五