synchronized对象设置为null

时间:2012-04-17 16:17:47

标签: java multithreading synchronization

我有两个帖子Thread1Thread2

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

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

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

5 个答案:

答案 0 :(得分:36)

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

答案 1 :(得分:12)

首先让我强调一下,修改用于同步的变量是非常糟糕的事情™。 obj1应为final,如果用作监视器,则永远不会被触及。

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

如果JVM首先执行Thread1,它会在obj1上进行同步,将其设置为null并退出该线程。第二个线程希望在obj1上进行同步,NullPointerException将被抛出。由于obj1的修改是在synchronized块中进行的,因此可以保证Thread2将看到更新的值(因此:NullPointerException是有保证的。)

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

答案 2 :(得分:4)

synchronized在对象上同步,而不是引用。通过将obj1(引用)设置为null,thread2无法在obj1以前指向的对象上进行同步,您将获得NullPointerException

答案 3 :(得分:1)

立即改变。当线程1“拥有”锁时,它可以随意改变obj1的值。线程2必须等到线程1释放锁定。肯定会看到obj1 == null

答案 4 :(得分:1)

快速解决方法是使对象成为1个元素的简单数组,并引用数组进行同步,例如,

Object [] obj1 = {null};

元素可以为null,而不会影响数组的存在。当然,这仍然违反了规则"不同步使用对象本身,但除非您的代码使其他地方的问题复杂化,否则此快速修复应该按预期工作。