1.9 一个同步方法是否可以调用另外一个同步方法?

2019-03-02  本文已影响0人  殊胜因缘_Chris
/**
 * This is description.
 * 一个同步方法是否可以调用另外一个同步方法?
 * 一个线程已经拥有某个对象的锁, 再次申请时, 是否还会得到该对象的锁?
 * 结论: 同一个线程执行, synchronized获取的锁是可重入的.(详见: <Java并发编程实战> P21)
 * 思考: 写一个程序模拟死锁.
 * @author Chris Lee
 * @date 2019/3/2 18:16
 */
public class Demo {
    /**
     * 同步方法fun1.
     */
    public synchronized void fun1() {
        System.out.println("当前线程: " + Thread.currentThread().getName() + ", fun1.");
        fun2();
    }

    /**
     * 同步方法fun2.
     */
    private synchronized void fun2() {
        System.out.println("当前线程: " + Thread.currentThread().getName() + ", fun2.");
    }

    public static void main(String[] args){
        Demo demo = new Demo();
        new Thread(() -> demo.fun1()).start();
        /*
            当前线程: Thread-0, fun1.
            当前线程: Thread-0, fun2.
         */
    }
}
思考:
/**
 * This is description.
 * 模拟死锁.
 * 思路:
 * 1. 两个线程t1, t2, 两个锁对象o1, o2.
 * 2. 在t1运行时先将o1加锁, sleep一下, 发现o2已被t2加锁.
 * 3. 在t2运行时先将o2加锁, sleep一下, 发现o1已被t1加锁.
 * 结果: 死锁产生.
 *
 * @author Chris Lee
 * @date 2019/3/3 12:32
 */
public class DeadLock implements Runnable {

    /**
     * flag = 1时, 将o1加锁.
     * flag = 2时, 将o2加锁.
     */
    private int flag = 1;

    /**
     * 定义两个静态对象o1, o2.(注: 类初次加载时会被初始化.)
     */
    public static Object o1 = new Object();
    public static Object o2 = new Object();

    @Override
    public void run() {

        if (flag == 1) {
            synchronized (o1) {
                System.out.println(Thread.currentThread().getName() + "flag = 1, o1加锁.");

                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (o2) {
                    System.out.println("flag = 2, o2加锁. 如果未打印, 则死锁产生.");
                }
            }
        } else if (flag == 2) {
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName() + "flag = 2, o2加锁.");

                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (o1) {
                    System.out.println("flag = 1, o1加锁. 如果未打印, 则死锁产生.");
                }
            }
        }
    }

    public static void main(String[] args) {
        DeadLock deadLock1 = new DeadLock();
        DeadLock deadLock2 = new DeadLock();

        deadLock1.flag = 1;
        deadLock2.flag = 2;

        new Thread(() -> deadLock1.run(), "线程t1: ").start();
        new Thread(() -> deadLock2.run(), "线程t2: ").start();
        /*
            线程t1: flag = 1, o1加锁.
            线程t2: flag = 2, o2加锁.
         */
    }
}

说明:
资料:
  1. 学习视频: https://www.bilibili.com/video/av11076511/?p=1
  2. 参考代码: https://github.com/EduMoral/edu/tree/master/concurrent/src/yxxy
  3. 我的代码: https://github.com/ChrisLeejing/learn_concurrency.git
上一篇 下一篇

猜你喜欢

热点阅读