Java并发实践: Listing 8. 3.引入锁顺序以防止死锁

标签 java multithreading

我无法理解为什么书中 list 8.3中提到的代码不容易出现死锁。当我运行代码时,它不会导致死锁。我借鉴了书中的想法并修改了代码。 以下是程序:-

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

    public static void main(String[] args) {

        LockOrderingDeadLockSolved obj = new LockOrderingDeadLockSolved();
        int leftHash = System.identityHashCode(obj.left);
        int rightHash = System.identityHashCode(obj.right);
        System.out.println(leftHash +" --- " + rightHash);
        Thread t = new Thread() {
            public void run() {
                if (leftHash < rightHash)
                    obj.leftRight();
                else if (leftHash > rightHash)
                    obj.rightLeft();
                else
                    obj.tieLockMethod();
            }
        };
        Thread t1 = new Thread() {
            public void run() {
                if (leftHash < rightHash)
                    obj.leftRight();
                else if (leftHash > rightHash)
                    obj.rightLeft();
                else
                    obj.tieLockMethod();
            }
        };
        t.start();
        t1.start();

    }

    private void leftRight() {
        synchronized (left) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            synchronized (right) {
                System.out.println("Left right -- left right lock");
            }
        }
    }

    private void rightLeft() {
        synchronized (right) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            synchronized (left) {
                System.out.println("Right left -- right left lock");
            }
        }
    }

    private void tieLockMethod() {
        synchronized (tieLock) {
            synchronized (left) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                synchronized (right) {
                    System.out.println("Right left --- tie lock");
                }
            }
        }
    }
}

输出:-

865113938 --- 1442407170

左右——左右锁

左右——左右锁

容易出现死锁的程序:-

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

public static void main(String[] args) {
    LockOrderingDeadLock obj = new LockOrderingDeadLock();
    Thread t = new Thread() {
        public void run() {
            obj.leftRight();
        }
    };
    Thread t1 = new Thread() {
        public void run() {
            obj.rightLeft();
        }
    };
    t.start();
    t1.start();

}

private void leftRight() {
    synchronized (left) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        synchronized (right) {
            System.out.println("Left right");
        }
    }
}

private void rightLeft() {
    synchronized (right) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        synchronized (left) {
            System.out.println("Right left");
        }
    }
}

}

最佳答案

如果以相同的顺序获取锁,则不会发生死锁。

为了使示例死锁,您必须以不同的顺序重复获取相同的锁。这可以通过以下代码来完成。

private static final Object left = new Object();
private static final Object right = new Object();

public static void main(String[] args) {
    Thread t1 = new Thread(() -> {
        while (true) {
            synchronized (left) {
                synchronized (right) {
                    System.out.println("Left right -- left right lock");
                }
            }
        }
    });
    Thread t2 = new Thread(() -> {
        while (true) {
            synchronized (right) {
                synchronized (left) {
                    System.out.println("Right left -- right left lock");
                }
            }
        }
    });
    t1.start();
    t2.start();
}

关于Java并发实践: Listing 8. 3.引入锁顺序以防止死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54695652/

相关文章:

java - 在没有 Maven 或 Gradle 的情况下将 JUnit 5 与 Java 9 结合使用

java - 更改 core.xml 中 Excel 文件的日期和时间格式 (ISO 8601)

java - BlazeDS 不处理 Java 内部类 DTO

java - thread local的用途和需求是什么

java - 在多线程环境中,对象创建是 Java 的瓶颈吗?

java - 将填充的数组传递给公共(public)变量,以便它可以在其他类中使用

java - 如何使用按钮按下操作在面板中显示图像

java - Nettys GlobalEventExecuter 是否利用当前线程?

iphone - 异步进程给我带来了麻烦

c# - 当两个线程都不是 WinForm 时,在两个线程之间引发事件