zoukankan      html  css  js  c++  java
  • java并发编程如何预防死锁

      在java并发编程领域已经有技术大咖总结出了发生死锁的条件,只有四个条件都发生时才会出现死锁:

     1.互斥,共享资源X和Y只能被一个线程占用

     2.占有且等待,线程T1已经取得共享资源X,在等待共享资源Y的时候,不释放共享资源X

     3.不可抢占,其他线程不能强行抢占线程T1占有的资源

     4.循环等待,线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,就是循环等待

      只要能破坏其中一个,就可以成功避免死锁的发生,因为对于共享资源我们要得就是互斥的效果,所以第一个条件是无法破坏的,所以可以从下面三个条件出手,具体实现方式:

     1.对于“占用且等待”这个条件,我们可以一次性申请所有的资源,这样就不存在等待了

      

    class Allocator{
            //通过破坏占有且等待条件避免死锁现象的发生
            private List<Object> als = new ArrayList<>();
            //一次申请所有的资源
            synchronized boolean apply(Object from, Object to){
                if (als.contains(from) || als.contains(to)){
                    //只要存在一个账户被其他的业务锁定则无法完成转账业务
                    return false;
                }else {
                    als.add(from);
                    als.add(to);
                }
                return true;
            }
            //归还资源
            synchronized void free(Object from,Object to){
                als.remove(from);
                als.remove(to);
            }
        }
        class Account {
            //actr应该为单例
            private Allocator actr;
            private int balance;
            //转账
            void  transfer(Account target, int amt){
                //一次性申请转出和转入账户,直到成功
                while (!actr.apply(this,target));
                try{
                    //锁定转出账户
                    synchronized (this){
                        //锁定转入账户
                        synchronized (target){
                            if (this.balance > amt){
                                this.balance -= amt;
                                target.balance += amt;
                            }
                        }
                    }
                }finally {
                    actr.free(this, target);
                }
            }
        }

     2.对于“不可抢占”这个条件,占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它所占有的资源,这样不可抢占这个条件就破坏掉了

     3.对于“循环等待”这个条件,可以靠按序申请资源来预防,所谓按序申请,是指资源是有线性顺序的,申请的时候可以先申请资源序号小的,再申请资源序号大的,这样线性化后自然就不存在循环了

        class Accounts{
            private int id;
            private int balance;
            //转账
            void  transfer(Accounts target,int amt){
                Accounts left = this;
                Accounts right = target;
                if (this.id > target.id){
                    left = target;
                    right = this;
                }
                //锁定序号小的账户
                synchronized (left){
                    //锁定序号大的账户
                    synchronized (right){
                        if (this.balance > amt){
                            this.balance -= amt;
                            target.balance += amt;
                        }
                    }
                }
            }
        }
  • 相关阅读:
    cf C. Vasya and Robot
    zoj 3805 Machine
    cf B. Vasya and Public Transport
    cf D. Queue
    cf C. Find Maximum
    cf B. Two Heaps
    cf C. Jeff and Rounding
    cf B. Jeff and Periods
    cf A. Jeff and Digits
    I Think I Need a Houseboat
  • 原文地址:https://www.cnblogs.com/hopeofthevillage/p/11599375.html
Copyright © 2011-2022 走看看