美文网首页
通过锁顺序来避免动态的锁顺序死锁

通过锁顺序来避免动态的锁顺序死锁

作者: 阿祥小王子 | 来源:发表于2018-11-16 20:58 被阅读0次

通过锁顺序来避免动态的锁顺序死锁

欢迎关注作者简书
csdn传送门

前言

  两个线程试图通过不同的顺序获取多个相同的锁。如果请求的顺序不相同,那么会出现循环的锁依赖现象,产生死锁。但是如果保证同时请求锁L和锁M的每一个线程,都是按照从 L 到 M 的顺序,那么就不会发生死锁了。
  比如:银行账户转账问题,两个用户转账的话,如果采用一般的synchronized嵌套的话,容易造成死锁。

思想

  我们可以制定锁的顺序,并在整个应用程序中,获得锁都必须始终遵守这个既定的顺序。我们在制定对象顺序的时候,可以使用System.identityHashCode这样一种方式,它会返回Object.hashcode所返回的值。 在极少数的情况下,2个对象具有相同的哈希码,我们必须使用任意的中数来决定锁的顺序,这又重新引入了死锁的可能性。这个时候我们使用另一个锁(加时赛锁),在获得2个对象的锁之前,就要获得这个锁。

/**
 * @program:
 * @description: 动态的锁顺序死锁的解决方案——通过锁顺序来避免死锁
 * @author: zhouzhixiang
 * @create: 2018-11-16 20:03
 */
public class ThreadTest5 {

    // 加时赛锁
    private static final Object tieLock = new Object();

    class Account implements Comparable{
        String username;
        String password;
        long moneycount;

        void debit(long amount) {
            moneycount = moneycount - amount;
        }

        void credit(long amount) {
            moneycount = moneycount + amount;
        }

        @Override
        public int compareTo(Object o) {
            return (int) (moneycount - ((long)o));
        }
    }

    /**
     * 此方法容易发生动态的锁顺序死锁——错误方式
     * @param fromAccount 转账方
     * @param toAccount   收账方
     * @param amount      转账金额
     */
    public void tranferMoney(Account fromAccount, Account toAccount, long amount) throws InsufficientResourcesException {
        synchronized(fromAccount) {
            synchronized (toAccount) {
                if(fromAccount.compareTo(amount) < 0)
                    throw new InsufficientResourcesException();
                else {
                    fromAccount.debit(amount);
                    toAccount.credit(amount);
                }
            }
        }
    }

    /**
     * 通过锁顺序来避免死锁——正确方法
     * @param fromAccount 转账方
     * @param toAccount   收账方
     * @param amount      转账金额
     */
    public void tranferMoney2(Account fromAccount, Account toAccount, long amount) throws InsufficientResourcesException {
        class Helper {
            public void tranfer() throws InsufficientResourcesException {
                if(fromAccount.compareTo(amount) < 0)
                    throw new InsufficientResourcesException();
                else {
                    fromAccount.debit(amount);
                    toAccount.credit(amount);
                }
            }
        }

        int fromHashCode = System.identityHashCode(fromAccount);
        int toHashCode = System.identityHashCode(toAccount);

        if(fromHashCode < toHashCode) {
            synchronized (fromAccount) {
                synchronized (toAccount) {
                    new Helper().tranfer();
                }
            }
        }else if (fromHashCode > toHashCode) {
            synchronized (toAccount) {
                synchronized (fromAccount) {
                    new Helper().tranfer();
                }
            }
        }else {
            // 加时赛锁
            synchronized (tieLock) {
                synchronized (fromAccount) {
                    synchronized (toAccount) {
                        new Helper().tranfer();
                    }
                }
            }
        }
    }


}
 

欢迎加入Java猿社区

欢迎加入Java猿社区.png

相关文章

  • 死锁

    线程饥饿死锁 锁顺序死锁 动态锁顺序死锁通过锁顺序来避免死锁 避免死锁

  • 通过锁顺序来避免动态的锁顺序死锁

    通过锁顺序来避免动态的锁顺序死锁 欢迎关注作者简书csdn传送门 前言   两个线程试图通过不同的顺序获取多个相同...

  • 死锁

    在JAVA编程中,有3种典型的死锁类型: 静态的锁顺序死锁 动态的锁顺序死锁 协作对象之间发生的死锁 静态的锁顺序...

  • java并发编程实战10:活跃性、性能与测试

    10.1 死锁 10.1.1 锁顺序死锁 如果所有线程以固定的顺序来获得锁,那么在程序中就不会出现锁顺序死锁问题。...

  • Java死锁笔记

    锁顺序死锁 动态锁顺序死锁 如果两个线程同时调用transferMoney()线程A从X账户向Y账户转账线程B从账...

  • Java concurrency《防止死锁》

    Java concurrency《防止死锁》 常见预防死锁的办法 有顺序的锁 具有超时时间的锁 死锁的检测 有顺序...

  • Java并发编程 -- 活跃性、性能与测试

    一、避免活跃性危险 1.死锁 锁顺序死锁:在线程A持有锁L并想获得锁M的同时,线程B持有锁M并尝试获得锁L,那么这...

  • 如何避免死锁

    避免死锁主要有 3种方式 加锁顺序 加锁时限 死锁检测 加锁顺序 一个线程如果要获取多个锁,必须按照一定的顺序去获...

  • 锁顺序死锁

    死锁形成的几个必要条件1、互斥2、等待3、不可抢占4、循环等待 避免死锁的方法就是,打破任一个必要条件。循环等待最...

  • 如何确保N个线程可以访问Nwh资源同时又不导致死锁

    使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所...

网友评论

      本文标题:通过锁顺序来避免动态的锁顺序死锁

      本文链接:https://www.haomeiwen.com/subject/rkjvfqtx.html