我尝试在下面的代码中同步一个对象:
public void myMethod() {
synchronized (globalObj) {
//Do something here
}
}
代码在一个线程中执行。问题是,另一个线程可能将'globalObj'设置为null。然后,当'globalObj'被其他线程设置为null时,'synchronized(globalObj)'将抛出NullPointerxception。
同步对象的最佳做法是什么,因此不会抛出NullPointerException?
感谢。
答案 0 :(得分:28)
您不应该在可能更改的引用上进行同步。如果允许另一个线程替换globalObj
,这意味着您可以锁定旧的globalObj
,而另一个线程可以使用完全不同的线程 - 锁定对您没有帮助。
您应该做的是为此目的单独Object
:
static final Object lockObj = new Object();
public void myMethod() {
synchronized (lockObj) {
// do something with globalObj here
}
}
由于lockObj
永远不会改变,因此您将始终使用相同的锁定 - 没有问题。
答案 1 :(得分:6)
您无法在null
引用上进行同步。最佳实践是在final
对象上进行同步(以确保它永远不会null
),或者(更好地)在java.util.concurrent
包中使用更高级别的并发抽象。
答案 2 :(得分:1)
确保在不能为null的对象上进行同步...
为什么要将globalObj
设置为null?这应该是什么样的并发语义?这是偶然的吗?
如果锁定的必要性有时会消失(虽然看起来很奇怪),你可以添加一个空检查(当然,你需要同步其他东西以避免首先检查null的竞争条件,然后拥有它之后立即设为null。
请更详细地描述您的情景。
答案 3 :(得分:0)
创建一个私有对象类成员,该成员没有任何公共setter并锁定该成员。