死锁

时间:2024-4-5    作者:老大夫    分类: JAVA


概念

不同的线程都在等待对方的线程结束而不放弃,造成了大家都在等待情况叫做死锁。

public class deadLocker {
    public static void main(String[] args) {
        StringBuilder sb1=new StringBuilder();
        StringBuilder sb2=new StringBuilder();

        new Thread(){
            @Override
            public void run() {
                synchronized (sb1){
                    sb1.append("a");
                    sb2.append("b");
                    synchronized (sb2){
                        sb1.append("a");
                        sb2.append("b");
                        System.out.println(sb1);
                        System.out.println(sb2);
                    }
                }
            }
        };
        new Thread(){
            @Override
            public void run() {
                synchronized (sb1){
                    sb1.append("c");
                    sb2.append("d");
                    synchronized (sb2){
                        sb1.append("c");
                        sb2.append("d");
                        System.out.println(sb1);
                        System.out.println(sb2);
                    }
                }
            }
        };
    }
}

死锁的发生原因

  1. 互斥条件
  2. 占用且等待
  3. 不可抢夺
  4. 循环等待

四个条件同时发生触发死锁

死锁的解决方法

死锁在程序内部形成很难人为干预

  1. 互斥无法避免,线程安全基于互斥原理防止线程同时进入。
  2. 可以考虑一次性申请所有需要的资源,这样就不需要等待
  3. 占用资源的线程如果进一步无法申请到下一步需要的资源,可以释放占用的资源。
  4. 可以将资源改为线性顺序,先申请序号较小的,这样可以避免循环的出现。

JUC的可重复锁ReentrantLock

jdk5.0引入的锁,是一种接口更加灵活

public class sale2 {
    public static void main(String[] args) {
        salePic2 s1=new salePic2();
        salePic2 s2=new salePic2();
        salePic2 s3=new salePic2();
        s1.start();
        s2.start();
        s3.start();
    }
}
class salePic2 extends Thread {
    static int total=10;
    //ReentrantLock时JUC中的可重复锁,创建锁的实例,确保多个线程共用一个锁,声明为static
    private static final ReentrantLock rl= new ReentrantLock();

    @Override
    public void run() {
        while(total>0){
            //重复锁调用锁的方法
            rl.lock();
            try {
                show();
            }finally {
                //重复锁调用解锁的方法,必须确保最后解锁的执行
                rl.unlock();
            }
        }
    }
    public static void show(){
        if (total>0){
            System.out.println(Thread.currentThread().getName()+"售出第"+total+"张票");
            total-=1;
        }
    }
}

总结

synchronized同步方法 锁的同步方式
不管同步代码块还是同步方法都是在{}结束后释放对同步监视器的调用 通过两个方法控制需要同步的代码
提供了多种实现类,适用于更多的复杂场景,效率更高

版权所有:伸手党盘
文章标题:死锁
文章链接:https://ssdpan.cn/?post=366
本站文章来源于网络搜集和原创,仅供学习使用,未经授权请勿用于任何商业用途,如有侵权及时联系删除

推荐阅读:


扫描二维码,在手机上阅读