多线程、死锁

1. 为什么要使用多线程?使用多线程可能带来什么问题?

使用多线程是为了提高程序的执行效率和运行速度。

但是如果使用不当的话,不仅不能提高执行效率,还会造成很多问题,比如:线程不安全、内存泄露,死锁等。

2. 造成线程死锁的原因有哪些?

线程死锁:多个线程同时被阻塞,他们中的一个或者多个都在等待某个资源被释放。由于线程被无限期阻塞,因此程序不可能被正常终止。

比如线程A拥有资源2,线程B拥有资源1,他们都想要对方的资源,但是在获取到需要的资源之前都没有释放自己本来拥有的资源,这就导致了这两个线程都在相互等待而进入死锁状态。

代码如下所示:

public class DeadLockDemo {
    public static void main(String[] args) {
        String lockA="lockA";
        String lockB="lockB";

        new Thread(new HoldLockThread(lockA,lockB),"Thread AAA").start();
     //   new Thread(new HoldLockThread(lockA,lockB),"Thread BBB").start();
        new Thread(new HoldLockThread(lockB,lockA),"Thread BBB").start();
    }
}

class HoldLockThread implements Runnable{
    private String lookA;
    private String lookB;

    public HoldLockThread(String lookA, String lookB) {
        this.lookA = lookA;
        this.lookB = lookB;
    }

    @Override
    public void run() {
        synchronized (lookA){
            System.out.println(Thread.currentThread().getName()+"\t 自己持有:"+lookA+"\t 尝试获得:"+lookB);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lookB){
                System.out.println(Thread.currentThread().getName()+"\t 已获得:"+lookA+"和"+lookB);
            }
            System.out.println("用完,释放:"+lookA+"和"+lookB);
        }
    }
}
Thread AAA	 自己持有:lockA	 尝试获得:lockB
Thread BBB	 自己持有:lockB	 尝试获得:lockA
  • 线程 A 通过 synchronized (lookA) 获得 lookA的监视器锁,然后通过TimeUnit.SECONDS.sleep(2);让线程 A 休眠 2s。

  • 为的是让线程 B 得到执⾏然后获取到 lookB的监视器锁。线程 A 和线程 B休眠结束了都开始企图请求获取对⽅的资源,然后这两个线程就会陷⼊互相等待的状态,这也就产⽣了死锁。

如果不想产生死锁,可以让B先获取lockA,再去获取lockB资源,这时候因为lockA被A占用,所以B只能等待A用完以后,才可以去获得资源。

Thread AAA	 自己持有:lockA	 尝试获得:lockB
Thread AAA	 已获得:lockA和lockB
用完,释放:lockA和lockB
Thread BBB	 自己持有:lockA	 尝试获得:lockB
Thread BBB	 已获得:lockA和lockB
用完,释放:lockA和lockB

2.1 产⽣死锁必须具备以下四个条件:

  1. 互斥条件 :该资源任意⼀个时刻只由⼀个线程占⽤。
  2. 请求与保持条件 :⼀个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件 :线程已获得的资源在末使⽤完之前不能被其他线程强⾏剥夺,只有⾃⼰使⽤完
    毕后才释放资源。
  4. 循环等待条件 :若⼲进程之间形成⼀种头尾相接的循环等待资源关系。

2.2 如何避免线程线程死锁呢?

  1. 破坏互斥条件 :这个条件我们没有办法破坏,因为我们⽤锁本来就是想让他们互斥的(临界
    资源需要互斥访问)。
  2. 破坏请求与保持条件 :⼀次性申请所有的资源。
  3. 破坏不剥夺条件 :占⽤部分资源的线程进⼀步申请其他资源时,如果申请不到,可以主动释
    放它占有的资源。
  4. 破坏循环等待条件 :靠按序申请资源来预防。按某⼀顺序申请资源,释放资源则反序释放。
    破坏循环等待条件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值