我有两个线程Thread1
和Thread2
//Within Thread1
synchronized(obj1)
{
obj1 = null;
}
//Within Thread2
synchronized(obj1)
{
do something
}
如果JVM首先执行线程1并将obj1设置为null,那么线程2会立即看到这个更改吗?还是需要时间,因为obj1尚未为null,JVM仍然可以运行线程2的同步块?
我有两个线程Thread1
和Thread2
//Within Thread1
synchronized(obj1)
{
obj1 = null;
}
//Within Thread2
synchronized(obj1)
{
do something
}
如果JVM首先执行线程1并将obj1设置为null,那么线程2会立即看到这个更改吗?还是需要时间,因为obj1尚未为null,JVM仍然可以运行线程2的同步块?
这几乎肯定会破坏同步抽象 - 我不能保证 thread2
立即看到更改。 您永远不应更改正在同步的对象的引用,更不用将其设置为 null
,这将导致任何进一步尝试对其进行同步时出现 NullPointerException
。
obj1
被用作监视器,它应该是final
且永远不应被更改。obj1
上进行同步,将其设置为null
,然后线程退出。第二个线程想要在obj1
上同步,会抛出NullPointerException
,因为在同步块中修改了obj1
,保证Thread2能看到更新后的值(所以:NullPointerException
是有保证的)。obj1
锁之后但在清除引用之前被中断,则线程2将锁定obj1
并等待Thread1完成。然后它将成功进入监视器,因为之前由obj1
引用的对象仍然存在。NullPointerException
是*不被保证的。在synchronized
块中执行写操作只能保证后续进入相同对象的synchronized
块的线程可见性,但不能保证在进入synchronized
块之前发生的读取。因此,在没有其他同步的情况下,第二个线程可能会抛出NullPointerException
,也可能不会,这是不可预测的。只有在synchronized
块内再次取消引用变量时,才能保证NullPointerException
的发生。 - Holgersynchronized
关键字锁定的是对象,而不是引用。如果将obj1
(一个引用)设置为null,那么线程2无法锁定以前由obj1
指向的对象,你会得到一个NullPointerException
异常。
Object [] obj1 = {null};
该元素可以为null,不影响数组的存在。尽管这仍然违反了不使用对象本身进行同步的“规则”,但除非您的代码在其他地方使问题复杂化,否则这个快速修复应该能够按预期工作。