码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-03-05 16:36:33      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:test   输出   div   rup   线程   lan   ati   todo   static   

起因

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

把它抽象出来就是:如果我再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个例子说明锁是锁在对象上的,而不是引用上的.

 

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

标签:test   输出   div   rup   线程   lan   ati   todo   static   

原文地址:http://www.cnblogs.com/abcwt112/p/6505578.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!