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

2019-04-07  本文已影响0人  jyjz2008

参考文章

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

思路

如果有两个锁 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();
    }
}

运行结果如下


运行结果
上一篇 下一篇

猜你喜欢

热点阅读