synchronized对象设置为null

我有两个线程Thread2Thread2

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

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

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

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

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

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

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

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

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

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

Object [] obj1 = {null};

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