java 同步语句上的 NullPointerException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6433493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:52:09  来源:igfitidea点击:

NullPointerException on synchronized statement

java

提问by Kai

I tried to synchronize on an object in my code below:

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

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

The code is executed in one thread. The issue is that, another thread may set 'globalObj' to null. Then, 'synchronized (globalObj)' will throw NullPointerxception when 'globalObj' has been set to null by other threads.

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

What's the best practice to synchronize on an object so NullPointerException will not be thrown?

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

Thanks.

谢谢。

回答by bdonlan

You should not be synchronizing on a reference that itself may be changed. If another thread is allowed to replace globalObj, that means you might hold a lock to the old globalObjwhile another thread works on an entirely different one - the lock doesn't help you at all.

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

What you should do instead is have a separate Objectfor this purpose:

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

static final Object lockObj = new Object();

public void myMethod() {
  synchronized (lockObj) {
    // do something with globalObj here
  }
}

Since lockObjnever changes, you'll always use the same lock - no problems.

由于lockObj永远不会改变,您将始终使用相同的锁 - 没问题。

回答by Daniel

You can't synchronize on a nullreference. The best practice is to synchronize on a finalobject (to ensure that it's never null), or (better still) use the higher level concurrency abstractions in the java.util.concurrentpackages.

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

回答by Thilo

Make sure you synchronize on an object that cannot be null...

确保在不能为空的对象上进行同步...

Why are you setting the globalObjto null? What should be the concurrency semantics for this? Is it by accident?

为什么要设置globalObj为空?这应该是什么并发语义?是偶然吗?

If the necessity to lock goes away sometimes (seems weird, though), you can add a null check (of course, you would need to synchronize on something else to avoid a race condition of first checking for null, and then having it set to null immediately afterwards).

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

Please describe your scenario in more detail.

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

回答by Marcus Leon

Create a private object class member which does not have any public setters and lock on that.

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