我有两个帖子Thread1
和Thread2
//Within Thread1
synchronized(obj1)
{
obj1 = null;
}
//Within Thread2
synchronized(obj1)
{
do something
}
如果jvm首先执行thread1并将obj1设置为null,那么thread2会立即看到该更改还是需要时间并且jvm仍然可以运行thread2 synchronized块,因为obj1还不是null?
答案 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,而不会影响数组的存在。当然,这仍然违反了规则"不同步使用对象本身,但除非您的代码使其他地方的问题复杂化,否则此快速修复应该按预期工作。