多线程与并发

1.18 建议用String常量作为锁定对象吗?

2019-03-16  本文已影响0人  殊胜因缘_Chris
/**
 * This is description.
 * Q: 建议用String常量作为锁定对象吗?
 * S: 不建议.
 * 不要以字符串常量作为锁定对象
 * 在下面的例子中, fun1和fun2其实锁定的是同一个对象
 * 这种情况还会发生比较诡异的现象, 比如你用到了一个类库, 在该类库中代码锁定了字符串“Hello”,
 * 但是你读不到源码, 所以你在自己的代码中也锁定了"Hello", 这时候就有可能发生非常诡异的死锁阻塞,
 * 因为你的程序和你用到的类库不经意间使用了同一把锁.(Jetty框架)
 *
 * @author Chris Lee
 * @date 2019/3/13 22:56
 */
public class Demo {
    static String s1 = "name";
    static String s2 = "name";

    public void fun1() {
        synchronized (s1) {

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

            }
        }
    }

    public void fun2() {
        // s1 == s2造成死锁, t2线程不打印.
        synchronized (s2) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName());

        // s1 != this, 此时不会造成死锁, t2线程打印.
        /*
        synchronized (this) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName());
        */
    }

    public static void main(String[] args) {
        System.out.println("s1 == s2: " + (s1 == s2));
        Demo demo = new Demo();
        new Thread(demo::fun1, "t1").start();
        new Thread(demo::fun2, "t2").start();
    }
}
说明:
资料:
  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
上一篇下一篇

猜你喜欢

热点阅读