欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于多线程中的死锁问题

程序员文章站 2022-05-02 16:55:45
...

关于多线程中的死锁问题

锁是非常有用的工具,运用场景非常多,因为它使用起来非常方便,而且易于理解。但同时它也会带来一些困扰,那就是可能引起死锁。

什么是死锁?

百度百科中对于死锁的定义:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

死锁产生的四个条件

  1. 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
  2. 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
  3. 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
  4. 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

来看一段代码,这段代码会引起死锁,使线程t1和线程t2互相等待对方释放锁。

package chapter1;

/**
 * Created by Chen on 2017/9/24.
 */
public class DeadLockDemo {
    private static String A = "A";
    private static String B = "B";

    public static void main(String[] args){
        new DeadLockDemo().deadLock();
    }

    private void deadLock() {
        Thread t1= new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A){
                    try{
                        Thread.currentThread().sleep(2000);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    synchronized (B){
                        System.out.println("1");
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B){
                    synchronized (A){
                        System.out.println("2");
                    }
                }
            }
        });
        t1.start();
        t2.start();
    }
}

分析一下上面这段程序,当t1线程拿到A锁进入到程序后,睡眠了2秒,此时,t2线程访问程序,拿到B锁,接下来,它要获取A锁,但是A锁在t1线程中,没有释放。而t1线程醒来后要得到B锁才能继续运行,此时的B锁又在t2线程中,两个线程互相等待对方释放锁,就形成了死锁。

避免死锁的几个常见方法

  1. 避免一个线程同时获取多个锁。
  2. 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  3. 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
  4. 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

参考《Java并发编程的艺术》