写一个可以产生死锁的 Java 程序

参考文章

码农翻身 一书中的第一个故事“我是一个线程”

思路

如果有两个锁 L1 L2, 线程 t1 持有 L1 且在尝试获取 L2, 线程 t2 持有 L2 且在尝试获取 L1 那么就会出现死锁了

程序

synchronized 语句块实现

我们可以在 class 对象上加锁
具体如下

public class DeadLock {

    public static void main(String[] args) throws Exception {
        class Naive implements Runnable {
            private final Class c1;
            private final Class c2;
            private String name;

            private Naive(String name, Class c1, Class c2) {
                this.name = name;
                this.c1 = c1;
                this.c2 = c2;
            }

            @Override
            public void run() {
                synchronized (c1) {
                    try {
                        // 让另一个线程有机会被调度, 这样另一个线程就有机会获得 c2 对应的锁了
                        Thread.sleep(1000);
                        System.out.println(String.format("%s acquired %s", name, c1));
                        synchronized (c2) {
                            System.out.println(String.format("%s acquired %s", name, c2));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        Thread t1 = new Thread(new Naive("t1", Integer.class, String.class));
        Thread t2 = new Thread(new Naive("t2", String.class, Integer.class));
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

运行结果如下


运行结果

ReentrantLock 来实现

也可以用 ReentrantLock 来实现,程序如下

package com.coder.rising;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DeadLock {

    public static void main(String[] args) throws Exception {
        class Naive implements Runnable {
            private final Lock lock1;
            private final Lock lock2;
            private String name;

            private Naive(String name, Lock lock1, Lock lock2) {
                this.name = name;
                this.lock1 = lock1;
                this.lock2 = lock2;
            }

            @Override
            public void run() {
                lock1.lock();
                try {
                    // 让另一个线程有机会被调度, 这样另一个线程就有机会获得 lock2 对应的锁了
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(String.format("%s acquired %s", name, lock1));
                lock2.lock();
                System.out.println(String.format("%s acquired %s", name, lock2));
                lock2.unlock();
                lock1.unlock();
            }
        }
        Lock lock1 = new ReentrantLock();
        Lock lock2 = new ReentrantLock();
        Thread t1 = new Thread(new Naive("t1", lock1, lock2));
        Thread t2 = new Thread(new Naive("t2", lock2, lock1));
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

运行结果如下


运行结果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容