这个java类线程安全吗?并发读写

时间:2012-12-06 23:24:52

标签: java concurrency

以下类线程是否安全?我担心并发读取和写入初始化变量。如果它不是线程安全的,如何使其线程安全?

  1. 我知道将methodA转换为synchronized会有所帮助,但我不想这样做
  2. 如何将volatile volatile keywork添加到“initialized”变量?
  3.  
    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添加到初始化将使其线程安全,这是正确的吗?

3 个答案:

答案 0 :(得分:3)

不,它不是线程安全的。调用init时,initialized例程可能正在设置methodA。由于methodA未同步,因此无法阻止执行initialized = trueif( !initialized)中的读取之间的竞争。实际上,写入甚至可能已经发生但尚未传播到调用methodA

的线程

volatile添加到initialized会有助于价值传播问题,但不会与第一个问题有关。

有关此内容的更多信息,我推荐Brian Goetz的文章Managing Volatility

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

总结:

  1. 如果在线程之间共享单个实例,则锁定实例变量
  2. 如果线程正在创建“安全”类的实例并且静态状态可能被这些线程修改,那么必须锁定静态(类)变量