alexRain的空间

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

测试代码如下:

 

 1 public class SyncNonFinalField {
 2     private Object object = new Object();
 3     public void start() {
 4         
 5         new Thread(new Runnable() {
 6             
 7             @Override
 8             public void run() {
 9                 System.out.println("线程1等待锁");
10                 synchronized (object) {
11                     System.out.println("线程1获取到了锁");
12                     object = new Object();
13                     System.out.println("线程1准备sleep");
14                     try {
15                         Thread.sleep(5000L);
16                     } catch (InterruptedException e) {
17                         e.printStackTrace();
18                     }
19                     System.out.println("线程1 sleep结束");
20                 }
21             }
22         }).start();
23         
24         new Thread(new Runnable() {
25             
26             @Override
27             public void run() {
28                 try {
29                     Thread.sleep(1000L);
30                 } catch (InterruptedException e) {
31                     e.printStackTrace();
32                 }
33                 System.out.println("线程2等待锁");
34                 synchronized (object) {
35                     System.out.println("线程2获取到了锁");
36                 }
37             }
38         }).start();
39     }
40 }

 

 

 

输出结果:

线程1等待锁
线程1获取到了锁
线程1准备sleep
线程2等待锁
线程2获取到了锁
线程1 sleep结束
 
也就是说,在线程1的同步块中,只要一给object重新赋值,线程2立即就进入到了同步块中
 
分析:
synchronized (object) 锁的是object这个引用所指向的对象,而不是锁引用。
线程1 sleep 时,并没有释放旧对象的锁。
但它让 object 指向了一个新对象之后,线程2就立即获取到了新对象的锁,所以线程2进入到了同步块中。
 
解决办法:
用final修饰object,避免它在同步块中被重新赋值。
posted on 2018-05-29 22:37  alexRain  阅读(2478)  评论(0编辑  收藏  举报