28

我有两个线程Thread1Thread2

//Within Thread1     
synchronized(obj1)  
{  
    obj1 = null;  
}  

//Within Thread2  
synchronized(obj1)  
{  
    do something  
}   

如果 jvm 首先执行 thread1 并将 obj1 设置为 null,那么 thread2 会立即看到该更改,还是需要时间并且 jvm 仍然可以运行 thread2 同步块,因为 obj1 尚未为 null?

4

5 回答 5

41

这几乎肯定会破坏同步抽象——我不相信thread2会立即看到变化。您永远不应该更改您正在同步的对象的引用,更不用说将其设置为null,这将导致NullPointerException任何进一步尝试对其进行同步。

于 2012-04-17T16:20:06.973 回答
15

首先让我强调,修改用于同步的变量是一件非常糟糕的事情。如果将其用作监视器,则obj1应该并且永远不要触摸。final

话虽如此,回到你的问题:

如果 JVM 首先执行 Thread1,它会同步 on obj1,将其设置为null,然后线程退出。第二个线程想要同步obj1NullPointerException将被抛出。因为修改obj1是在同步块中进行的,所以保证 Thread2 会看到更新的值(所以:NullPointerException保证)。

如果 Thread1 在获得锁后obj1但在清除引用之前被中断,则 Thread2 将锁定obj1并等待直到 Thread1 完成。然后它将成功进入监视器,因为之前引用的对象obj1仍然存在。

于 2012-04-17T16:22:25.033 回答
5

synchronized synchronizes on the object, and not the reference. By setting obj1 (a reference) to null, thread2 can't synchronize on the object formerly pointed to by obj1, you'll get a NullPointerException instead.

于 2012-04-17T17:43:16.977 回答
2

A quick fix is to make the object a simple array of 1 element and refer to the array for synchronization, e.g.,

Object[] obj1 = {null};

The element can be null without impacting the existence of the array. Granted, this still breaks the "rule" of not using the object itself in synchronization, but unless your code complicates matters elsewhere, this quick fix should work as expected.

于 2014-04-28T14:41:59.900 回答
1

The change is immediate. When Thread 1 "owns" the lock, it can change the value of obj1 at will. Thread 2 has to wait until Thread 1 releases the lock. It will definitely see obj1 == null

于 2012-04-17T17:47:39.790 回答