我有两个线程Thread1
和Thread2
//Within Thread1
synchronized(obj1)
{
obj1 = null;
}
//Within Thread2
synchronized(obj1)
{
do something
}
如果JVM首先执行线程1和套OBJ1为空,然后将线程2立即看到这种变化还是会花时间和JVM仍然可以运行线程2 synchronized块,因为OBJ1还没有空?
这几乎肯定会打破同步的抽象-我不会相信, thread2
将立即看到变化。 你不应该改变你同步的对象的引用,更不用说将它设置为null
,这将导致一个NullPointerException
上的任何进一步尝试就可以同步。
首先我要强调的是,修改用于同步的变量是一个非常糟糕的事情 ™。 obj1
应该是final
,如果它被用作显示器从来没有被触及。
话虽这么说,回到你的问题:
如果JVM首先执行线程1,它同步于obj1
,将它设置为null
并且该线程退出。 第二个线程希望在同步obj1
, NullPointerException
将被抛出。 因为修改obj1
在同步块构成的,它保证了线程2将看到更新的值(因此: NullPointerException
保证)。
如果线程1被获取的锁后中断obj1
但清除引用之前,线程2将锁定obj1
,等待线程1完成。 然后,它会顺利进入显示器,因为先前引用的对象obj1
仍然存在。
synchronized
同步的对象,而不是参考。 通过设置obj1
(参考)为null,线程2不能以前由指向的对象上同步obj1
,你会得到一个NullPointerException
来代替。
这种变化是立竿见影的。 当线程1“拥有”的锁,它可以随意改变OBJ1的价值。 线程2要等到线程1解除锁定。 它一定会看到OBJ1 == NULL
快速的解决办法是使加工对象物1个元件的简单阵列,并且是指该阵列用于同步,例如,
对象[] OBJ1 = {NULL};
所述元件可以为空而不影响阵列的存在。 当然,这还打破了不使用同步对象本身的“规则”,但除非你的代码的其他地方复杂事项,预计今年速战速决应该工作。