首先介绍下什么是死锁?
个人理解:死锁指的是在多线程中(至少存在2个线程),线程之间持有各自所需要的锁,互相等待对方释放锁资源,形成无限等待的情况,这种场景叫做死锁
上面那句话可能不是很好理解,我举一个例子:
有两个人,一个叫小明,一个叫小红,他们关系特别好,吃饭共用一套碗筷
到饭点了,小明和小红一起去吃饭,小明先拿到了碗,正准备拿筷子的时候,却被小红抢先一步,
小明说:你把筷子给我,我要先去吃饭,吃完给你,小红不肯,说:你先把碗给我,我吃完了再给你
这样两个人,你不让我,我不让你,互怼,形成一种僵持的局面,
最后两个人都没吃到饭,然后 ‘卒’,享年9岁
上面的 例子中,小明和小红代表了程序中的两个线程,而碗和筷子代表了锁资源,而吃饭的动作相当于后续要执行的业务逻辑,只有同时拥有了碗和筷子才能 吃饭。
相信看完上面例子,你对死锁应该会有一个比较初步清晰的认识
那么什么情况下为什么会产生死锁呢?
出现死锁,一般发生在同步方法嵌套的场景中,像下面这样子
private void test() {
synchronized (obj1) {
XXXXX代码
synchronized (obj2) {
xxx代码
}
}
}
或者这样子
同步方法,自带this锁
private synchronized void test() {
synchronized (obj) {
xxxxx代码
}
}
这里只列了2层锁嵌套,可能还有3层,4层,5层。。。。为了简单,好理解就不列了那么多了
说了那么多,那么怎么模拟出死锁呢?
不说太多废话了,直接上代码吧
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
TestThread2 testThread2 = new TestThread2();
testThread2.setFlag(true);
Thread thread1 = new Thread(testThread2,"线程A");
Thread thread2 = new Thread(testThread2,"线程B");
thread1.start();
Thread.sleep(10);//这里休眠的目的是让线程A先执行,保证A线程进入if里面,B线程进入else里面
testThread2.setFlag(false);
thread2.start();
}
}
public class TestThread2 implements Runnable {
private int count=100000;
private Object obj=new Object();
private boolean flag;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag) {
synchronized (obj) {
try {
System.out.println(Thread.currentThread().getName()+"拿到了obj锁");
Thread.sleep(40);//这里休眠是让B线程有机会拿到this锁
} catch (InterruptedException e) {
e.printStackTrace();
}
decrCount();
}
}else{
decrCount();
}
}
//同步方法默认使用this锁
private synchronized void decrCount() {
System.out.println(Thread.currentThread().getName()+"拿到了this锁");
//这里一定要加上obj锁才能成功模拟出死锁的场景
synchronized (obj) {
while (count >0){
System.out.println(Thread.currentThread().getName()+":"+count);
count--;
}
}
}
}
有啥不懂的,可以加群798733709一起交流学习,群里很多都是工作4-5年的大牛。
写文章是在是太难了 ,如果有帮到你,点个赞再走呗
来源:oschina
链接:https://my.oschina.net/u/4271739/blog/4408916
标签: