• 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;
                        }
                    }
                }
            }
        }
  • 相关阅读:
    已解决】Sublime中运行带input或raw_input的Python代码出错:EOFError: EOF when reading a line(转)
    暂时解决Sublime Text 2不支持input问题(转)
    Python中的注释(转)
    You don't have permission to access / on this server
    mysql开启慢查询方法(转)
    php获取当前url完整地址
    js中日期转换为时间戳
    发现js端日期跟php端日期格式不一致
    首发Zend Studio正式版注册破解(转)
    Arduino入门笔记(3):单LED闪烁
  • 原文地址:https://www.cnblogs.com/hopeofthevillage/p/11599375.html
Copyright © 2020-2023  润新知