美文网首页
Java死锁笔记

Java死锁笔记

作者: R7_Perfect | 来源:发表于2019-08-06 14:08 被阅读0次

锁顺序死锁

public class LeftRightDeadlock {
    private final Object left = new Object();
    private final Object right = new Object();

    public void leftRight() {
        // 得到left锁
        synchronized (left) {
            // 得到right锁
            synchronized (right) {
                doSomething();
            }
        }
    }

    public void rightLeft() {
        // 得到right锁
        synchronized (right) {
            // 得到left锁
            synchronized (left) {
                doSomethingElse();
            }
        }
    }
}

动态锁顺序死锁

 // 转账
    public static void transferMoney(Account fromAccount,
                                     Account toAccount,
                                     DollarAmount amount)
            throws InsufficientFundsException {

        // 锁定汇账账户
        synchronized (fromAccount) {
            // 锁定来账账户
            synchronized (toAccount) {

                // 判余额是否大于0
                if (fromAccount.getBalance().compareTo(amount) < 0) {
                    throw new InsufficientFundsException();
                } else {

                    // 汇账账户减钱
                    fromAccount.debit(amount);

                    // 来账账户增钱
                    toAccount.credit(amount);
                }
            }
        }
    }

如果两个线程同时调用transferMoney()
线程A从X账户向Y账户转账
线程B从账户Y向账户X转账
那么就会发生死锁。

固定锁顺序避免死锁

public class InduceLockOrder {

    // 额外的锁、避免两个对象hash值相等的情况(即使很少)
    private static final Object tieLock = new Object();

    public void transferMoney(final Account fromAcct,
                              final Account toAcct,
                              final DollarAmount amount)
            throws InsufficientFundsException {
        class Helper {
            public void transfer() throws InsufficientFundsException {
                if (fromAcct.getBalance().compareTo(amount) < 0)
                    throw new InsufficientFundsException();
                else {
                    fromAcct.debit(amount);
                    toAcct.credit(amount);
                }
            }
        }
        // 得到锁的hash值
        int fromHash = System.identityHashCode(fromAcct);
        int toHash = System.identityHashCode(toAcct);

        // 根据hash值来上锁
        if (fromHash < toHash) {
            synchronized (fromAcct) {
                synchronized (toAcct) {
                    new Helper().transfer();
                }
            }

        } else if (fromHash > toHash) {// 根据hash值来上锁
            synchronized (toAcct) {
                synchronized (fromAcct) {
                    new Helper().transfer();
                }
            }
        } else {// 额外的锁、避免两个对象hash值相等的情况(即使很少)
            synchronized (tieLock) {
                synchronized (fromAcct) {
                    synchronized (toAcct) {
                        new Helper().transfer();
                    }
                }
            }
        }
    }
}

得到对应的hash值来固定加锁的顺序

协作对象之间发生死锁

public class CooperatingDeadlock {
    // Warning: deadlock-prone!
    class Taxi {
        @GuardedBy("this") private Point location, destination;
        private final Dispatcher dispatcher;

        public Taxi(Dispatcher dispatcher) {
            this.dispatcher = dispatcher;
        }

        public synchronized Point getLocation() {
            return location;
        }

        // setLocation 需要Taxi内置锁
        public synchronized void setLocation(Point location) {
            this.location = location;
            if (location.equals(destination))
                // 调用notifyAvailable()需要Dispatcher内置锁
                dispatcher.notifyAvailable(this);
        }

        public synchronized Point getDestination() {
            return destination;
        }

        public synchronized void setDestination(Point destination) {
            this.destination = destination;
        }
    }

    class Dispatcher {
        @GuardedBy("this") private final Set<Taxi> taxis;
        @GuardedBy("this") private final Set<Taxi> availableTaxis;

        public Dispatcher() {
            taxis = new HashSet<Taxi>();
            availableTaxis = new HashSet<Taxi>();
        }

        public synchronized void notifyAvailable(Taxi taxi) {
            availableTaxis.add(taxi);
        }

        // 调用getImage()需要Dispatcher内置锁
        public synchronized Image getImage() {
            Image image = new Image();
            for (Taxi t : taxis)
                // 调用getLocation()需要Taxi内置锁
                image.drawMarker(t.getLocation());
            return image;
        }
    }

    class Image {
        public void drawMarker(Point p) {
        }
    }
}

上面的getImage()和setLocation(Point location)都需要获取两个锁的
并且在操作途中是没有释放锁的
这就是隐式获取两个锁(对象之间协作)..
这种方式也很容易就造成死锁.....

开放调用避免死锁

class CooperatingNoDeadlock {
    @ThreadSafe
    class Taxi {
        @GuardedBy("this") private Point location, destination;
        private final Dispatcher dispatcher;

        public Taxi(Dispatcher dispatcher) {
            this.dispatcher = dispatcher;
        }

        public synchronized Point getLocation() {
            return location;
        }

        public void setLocation(Point location) {
            boolean reachedDestination;

            // 加Taxi内置锁
            synchronized (this) {
                this.location = location;
                reachedDestination = location.equals(destination);
            }
            // 执行同步代码块后完毕,释放锁

            if (reachedDestination)
                // 加Dispatcher内置锁
                dispatcher.notifyAvailable(this);
        }

        public synchronized Point getDestination() {
            return destination;
        }

        public synchronized void setDestination(Point destination) {
            this.destination = destination;
        }
    }

    @ThreadSafe
    class Dispatcher {
        @GuardedBy("this") private final Set<Taxi> taxis;
        @GuardedBy("this") private final Set<Taxi> availableTaxis;

        public Dispatcher() {
            taxis = new HashSet<Taxi>();
            availableTaxis = new HashSet<Taxi>();
        }

        public synchronized void notifyAvailable(Taxi taxi) {
            availableTaxis.add(taxi);
        }

        public Image getImage() {
            Set<Taxi> copy;

            // Dispatcher内置锁
            synchronized (this) {
                copy = new HashSet<Taxi>(taxis);
            }
            // 执行同步代码块后完毕,释放锁

            Image image = new Image();
            for (Taxi t : copy)
                // 加Taix内置锁
                image.drawMarker(t.getLocation());
            return image;
        }
    }

    class Image {
        public void drawMarker(Point p) {
        }
    }

}

使用定时锁

使用显式Lock锁,在获取锁时使用tryLock()方法。当等待超过时限的时候,tryLock()不会一直等待,而是返回错误信息。
使用tryLock()能够有效避免死锁问题~~

相关文章

  • Java高并发 -- 并发扩展

    Java高并发 -- 并发扩展 主要是学习慕课网实战视频《Java并发编程入门与高并发面试》的笔记 死锁 死锁是指...

  • java笔记--死锁

    死锁: 常见情景之一:同步的嵌套 :(面试的时候可能直接让写)

  • Java死锁笔记

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

  • Java死锁检测之ThreadMXBean

    看此文章前请先了解之前一篇文章 "Java死锁之理解死锁" 中的死锁示例java 中提供了可以检测死锁的工具类Th...

  • Java concurrency《防止死锁》

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

  • 如何去检测死锁

    如何检测死锁 死锁预防 让线程获取锁的顺序一致 死锁检测 jps 查看java 进程信息 jstack +进程号 ...

  • 死锁

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

  • Java死锁的简单例子

    Java死锁的简单例子 两个线程互相占有对方需要的资源而不释放,便形成了死锁。 代码如下:Program.java...

  • JVM_JMM: 死锁的检测

    死锁的示例代码: 通过jconsole来检测死锁: 名称: Thread-1状态: java.lang.Class...

  • java死锁介绍、源码实现及预防(含源码)

    java死锁介绍、源码实现及预防(含源码) 什么是死锁 死锁是 多个线程 之间 相互之间 持有 对方需要的资源,同...

网友评论

      本文标题:Java死锁笔记

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