死锁

所谓死锁,就是两个线程互相等待对方释放锁,即A持有B要获取的锁,B持有A要获取的锁,然后B要获取A持有的锁,A要获取B持有的锁。

所以死锁至少有两把锁,对于只有一把锁的情况,不会出现死锁,只是阻塞Block状态,当持有线程释放掉锁的之后,其他线程就可以继续获取锁。

模拟下死锁,示例代码:

public class DeadLock {
    static Object o1 = new Object();
    static Object o2 = new Object();

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock1();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                lock2();
            }
        }).start();

    }

    public static void lock1(){
        synchronized (o1){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("o2执行完毕");
            }
            System.out.println("o1执行完毕");
        }
    }

    public static void lock2(){
        synchronized (o2){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("o2执行完毕");
        }
    }
}

程序执行之后,栈内信息如下:


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x000000001c0af638 (object 0x000000076b742460, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000001c0acda8 (object 0x000000076b742470, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at com.test.DeadLock.lock2(DeadLock.java:56)
	- waiting to lock <0x000000076b742460> (a java.lang.Object)
	- locked <0x000000076b742470> (a java.lang.Object)
	at com.test.DeadLock$2.run(DeadLock.java:22)
	at java.lang.Thread.run(Thread.java:748)
"Thread-0":
	at com.test.DeadLock.lock1(DeadLock.java:37)
	- waiting to lock <0x000000076b742470> (a java.lang.Object)
	- locked <0x000000076b742460> (a java.lang.Object)
	at com.test.DeadLock$1.run(DeadLock.java:15)
	at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

 

在我们实际开发中,死锁的情况不是很多,但是之前的确处理过死锁的案例。我遇到的案例大概是这样的

表A和表B没有太大关联。单看某个业务方法,并没有啥问题,但是当实际运行的时候,大部分时间也不会遇到问题,但是一旦出现有一个业务线程调用了业务方法1并且执行了删除表A数据D1,这个时候另一个线程的业务调用了业务方法2并且执行链路删除数据B数据D2, 此时第一个线程要执行删除表B数据D2,第二个线程要执行删除表A数据D1的时候,两个线程造成了死锁。这个是行锁,如果是表锁会更加容易复现。我们也可以通过数据库的两个窗口进行模拟这种死锁。

所以我们在做业务的时候,尽量避免这种情况。避免这种情况也很简单,要么就把删除A和删除B的业务单独抽离出来,所有需要删除A或删除B的都调我统一的服务来执行。要么两个业务执行的顺序要一致,先删A再删B或者先删B再删A,一致的话也不会造成死锁。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值