• 在同步块中修改指向同步对象的引用


    起因

    最近上网突然看到别人提的一个问题,感觉蛮有趣的,自己重来没有想过.

    把它抽象出来就是:如果我再synchronized中锁住了一个对象,然后在同步块中修改了指向这个对象的引用会怎么样?

    实验

     1 public class SynchronizedTest1 implements Runnable {
     2     public static Object lock = new Object();
     3 
     4     @Override
     5     public void run() {
     6         synchronized (lock) {
     7             System.out.println(Thread.currentThread().getName() + lock);
     8             lock = new Object();
     9             try {
    10                 Thread.sleep(1000);
    11             } catch (InterruptedException e) {
    12                 // TODO Auto-generated catch block
    13                 e.printStackTrace();
    14             }
    15             System.out.println(Thread.currentThread().getName() + lock);
    16         }
    17     }
    18 
    19     public static void main(String[] args) {
    20         Thread t1 = new Thread(new SynchronizedTest1());
    21         Thread t2 = new Thread(new SynchronizedTest1());
    22         t1.start();
    23         t2.start();
    24     }
    25 
    26 }

    可能的输出:

    Thread-0java.lang.Object@153bcbc8
    Thread-1java.lang.Object@8bfc25c
    Thread-0java.lang.Object@65712a80
    Thread-1java.lang.Object@65712a80

    这说明在线程0做完lock=new Object()的时候,线程1可以立刻进入同步块.

    另外1个例子:

     1 public class SynchronizedTest2 implements Runnable {
     2     public static String lock = "123";
     3 
     4     @Override
     5     public void run() {
     6         synchronized (lock) {
     7             System.out.println(Thread.currentThread().getName() + lock);
     8             lock = "123";
     9             try {
    10                 Thread.sleep(1000);
    11             } catch (InterruptedException e) {
    12                 // TODO Auto-generated catch block
    13                 e.printStackTrace();
    14             }
    15             System.out.println(Thread.currentThread().getName() + lock);
    16         }
    17     }
    18 
    19     public static void main(String[] args) {
    20         Thread t1 = new Thread(new SynchronizedTest2());
    21         Thread t2 = new Thread(new SynchronizedTest2());
    22         t1.start();
    23         t2.start();
    24     }
    25 
    26 }

    输出:

    Thread-0123
    Thread-0123
    Thread-1123
    Thread-1123

    线程0和线程1不会交叉输出.

    结论

    2个例子的差别就是第二个例子里因为有常量池的原因,lock永远指向的是同一个String对象,所以虽然在线程0中修改了lock的指向,但是还是指向了同一个String对象,所以线程1还是在synchronized那里阻塞.

    而在例子一中,当lock=new Object()的时候线程1可以即可进入synchronized,因为这个时候线程1synchronzed的对象已经和线程0synchronized的对象不同了.

    这2个例子说明锁是锁在对象上的,而不是引用上的.

  • 相关阅读:
    转载《XAMPP安装和使用教程》(转)
    EA经典教程(转)
    something to note
    XAMPP安装说明及操作指南 (转)
    Use vCard Objects in RDF/XML (转)
    word2007的相关操作如删除标记区等 及firefox 修改颜色
    jsp和servlet重定向
    HowToMakeCustomSearch
    关于树型dropdownlist的绑定
    在ASP.NET中显示进度条
  • 原文地址:https://www.cnblogs.com/abcwt112/p/6505578.html
Copyright © 2020-2023  润新知