java多线程:死锁

死锁

  • 在多道程序系统中,一组进程中的每一个进程无限期的等待被该组进程中的另一个进程占有且永远不会释放的资源,这种现象称系统处于死锁状态,处于死锁状态的进程称为死锁进程。

  • 某一个同步块中同时拥有两个以上对象的锁时,就可能会发生死锁的问题

  • 产生死锁的必要条件

    • 互斥条件:一个资源一次只能被一个进程所使用,即是排它性使用。 临界资源
    • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源要求,而该资源又已被其它进程占有,此时请求进程阻塞,但又对已经获得的其它资源保持不放。
    • 不可抢占条件(不可剥夺):一个资源仅能被占有它的进程所释放,而不能被别的进程强占。
    • 循环等待条件:在出现死锁的系统中,一定存在一个进程—资源的环形请求链。
  • 死锁的预防

    1. 破坏“互斥”条件:临界资源必须互斥访问,是某些资源使用时所必须要求的,不能加以改变,所以不易有解决方案。
    2. 破坏“不可剥夺(抢占)”条件:一个进程在使用某资源过程可以暂时放弃该资源,即允许其他进程剥夺使用该资源,从而破坏了“不剥夺”条件的出现。 该策略实现起来相当困难,为了保护在自动放弃资源时的现场以及以后的恢复现场,需要付出很高的代价。可能出现进程反复地申请和释放某些资源而被无限延迟执行。
    3. 破坏“请求和保持”条件:为了能破坏“请求和保持”条件,系统必须保证做到:当一个进程在请求资源时,它不能持有不可抢占资源
    4. 破坏“循环等待”条件:采用资源顺序分配法,可以破坏循环等待条件:给系统中的资源编号 (唯一),每个进程只能按序号由小到大的顺序申请资源,否则系统不予分配。
      • 优点:有序资源分配法提高了资源利用率
        缺点:顺序号与实际需要资源的顺序不一致,导致资源的浪费。
    //死锁
    public class DeadLock {
        public static void main(String[] args) {
            Makeup g1 = new Makeup(0, "aaa");
            Makeup g2 = new Makeup(1, "bbb");
    
            g1.start();
            g2.start();
        }
    }
    //口红
    class Lipstick{
    
    }
    //镜子
    class Mirror{
    
    }
    class Makeup extends Thread{
        //需要的资源只有一份,用static来保证只有一份
        static Lipstick lipstick = new Lipstick();
        static Mirror mirror = new Mirror();
        int choice;//选择
        String girlName;//使用化妆品的人
    
        public Makeup(int choice, String girlName) {
            this.choice = choice;
            this.girlName = girlName;
        }
    
        @Override
        public void run() {
           //化妆
            try {
                makeup();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //化妆,互相持有对方的锁
        private void makeup() throws InterruptedException {
            if (choice == 0) {
                synchronized (lipstick) {//获得口红的锁
                    System.out.println(this.girlName + "获得口红的锁");
                    Thread.sleep(1000);
    
                    synchronized (mirror) {//一秒钟后想获得镜子
                        System.out.println(this.girlName + "获得镜子的锁");
                    }
                }
            } else {
                synchronized (mirror) {//获得镜子的锁
                    System.out.println(this.girlName + "获得镜子的锁");
                    Thread.sleep(1000);
    
                    synchronized (lipstick) {//一秒钟后想获得口红
                        System.out.println(this.girlName + "获得口红的锁");
                    }
                }
            }
        }
    }
    //发生死锁:
    //aaa获得口红的锁
    //bbb获得镜子的锁
    
    //////////////////////////////////////////////////////////////////
    //避免死锁
    private void makeup() throws InterruptedException {
            if (choice == 0) {
                synchronized (lipstick) {//获得口红的锁
                    System.out.println(this.girlName + "获得口红的锁");
                    Thread.sleep(1000);
                }
                synchronized (mirror) {//一秒钟后想获得镜子
                    System.out.println(this.girlName + "获得镜子的锁");
                }
            } else {
                synchronized (mirror) {//获得镜子的锁
                    System.out.println(this.girlName + "获得镜子的锁");
                    Thread.sleep(1000);
                }
                synchronized (lipstick) {//一秒钟后想获得口红
                    System.out.println(this.girlName + "获得口红的锁");
                }
            }
        }
    //aaa获得口红的锁
    //bbb获得镜子的锁
    //bbb获得口红的锁
    //aaa获得镜子的锁
    
posted @ 2021-01-24 17:26  迪迦是真的  阅读(77)  评论(0)    收藏  举报
//复制代码按钮 //代码行号 //评论