1

下面的类线程安全吗?我担心并发读写初始化变量。如果它不是线程安全的,如何使它成为线程安全的?

  1. 我知道将 methodA 转换为同步会有所帮助,但我不想这样做
  2. 如何将 volatile 密钥添加到“初始化”变量?
public class A {

    private boolean initialized;

    public synchronized void init(String configFilePath) {
        if (initialized) {
            return;
        }

        initialized = true;
    }

    public void methodA() {
        if (!initialized) {
            throw new ConfigurationException()
        }
    }
}

Update1:​​初始化的变量在init方法中只会被修改一次,其他方法只会准备好。如果是这种情况,将 volatile 添加到 initialized 将使其线程安全,对吗?

4

3 回答 3

3

不,它不是线程安全的。当被调用时,init例程可能处于设置中间。由于不同步,因此没有什么可以阻止执行和读入之间的竞争。事实上,写入甚至可能已经发生,只是还没有传播到调用的线程initializedmethodAmethodAinitialized = trueif( !initialized)methodA

添加volatiletoinitialized将有助于解决价值传播问题,但不适用于第一个问题。

有关这方面的更多信息,我推荐 Brian Goetz 的文章管理波动性

于 2012-12-06T23:27:47.720 回答
0

不,它不是线程安全的。你必须同步。

于 2012-12-06T23:31:59.070 回答
0

@HotLicks 是 100% 正确的。任何有关并发的问题都需要提供上下文。原因如下:

让我们假设一个类已被编写为“安全”(暂时忽略 OPs 类)。如果您正在对实例变量进行同步并且该类的实例由许多线程共享,那么它将是线程安全的。但是,如果可以(由不同的线程)创建类的多个实例,并且它们可能会修改静态变量/状态,那么只有在静态(即类)变量上同步时它才会是线程安全的。

总之:

  1. 如果在线程之间共享单个实例,则锁定实例变量
  2. 如果线程正在创建“安全”类的实例并且静态状态可能被这些线程修改,则必须锁定静态(类)变量
于 2012-12-07T02:20:06.513 回答