同步语句的NullPointerException

我尝试在下面的代码中同步一个对象:

public void myMethod() { synchronized (globalObj) { //Do something here } } 

代码在一个线程中执行。 问题是,另一个线程可能将’globalObj’设置为null。 然后,当’globalObj’被其他线程设置为null时,’synchronized(globalObj)’将抛出NullPointerxception。

什么是在对象上同步的最佳实践,因此不会抛出NullPointerException?

谢谢。

您不应该在可能更改的引用上进行同步。 如果允许另一个线程替换globalObj ,这意味着您可以保持对旧的globalObj的锁定,而另一个线程在完全不同的线程上工作 – 锁定对您没有任何帮助。

你应该做的是为此目的有一个单独的Object

 static final Object lockObj = new Object(); public void myMethod() { synchronized (lockObj) { // do something with globalObj here } } 

由于lockObj永远不会改变,所以你总是会使用相同的锁 – 没问题。

您无法在null引用上进行同步。 最佳实践是在final对象上进行同步(以确保它永远不为null ),或者(更好地)在java.util.concurrent包中使用更高级别的并发抽象。

确保在不能为null的对象上进行同步…

为什么globalObj设置为null? 这应该是什么样的并发语义? 这是偶然的吗?

如果锁定的必要性有时消失(虽然看起来很奇怪),你可以添加一个空检查(当然,你需要同步其他东西以避免首先检查null的竞争条件,然后将其设置为之后立即为null)。

请更详细地描述您的场景。

创建一个私有对象类成员,该成员没有任何公共setter并锁定该成员。