Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个java类是线程安全的吗?并发读写_Java_Concurrency - Fatal编程技术网

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

这个java类是线程安全的吗?并发读写,java,concurrency,Java,Concurrency,下面的类是线程安全的吗?我担心并发读写初始化变量。如果它不是线程安全的,如何使其线程安全 我知道将methodA转换为synchronized会有帮助,但我不想这样做 将volatile keywork添加到“initialized”变量中如何 更新1: 初始化的变量在init方法中只修改一次,所有其他方法只准备就绪。如果是这种情况,将volatile添加到initialized将使其成为线程安全的,对吗?不,它不是线程安全的。 init < /Cord>例程可以设置在初始化 > 方法> < /

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

  • 我知道将methodA转换为synchronized会有帮助,但我不想这样做
  • 将volatile keywork添加到“initialized”变量中如何
  • 更新1:
    初始化的变量在init方法中只修改一次,所有其他方法只准备就绪。如果是这种情况,将volatile添加到initialized将使其成为线程安全的,对吗?

    不,它不是线程安全的。<代码> init < /Cord>例程可以设置在<代码>初始化 > <代码>方法> < /C> >。由于
    methodA
    未同步,因此执行
    initialized=true
    与读取
    if(!initialized)
    之间没有任何冲突。事实上,写操作甚至可能已经发生,但还没有传播到调用
    methodA

    volatile
    添加到
    initialized
    将有助于解决值传播问题,但对第一个问题没有帮助

    关于这方面的更多信息,我推荐Brian Goetz的文章。

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

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

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

    总之:

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

  • 该类肯定不是线程安全的,使
    初始化
    变量
    volatile
    不会使其线程安全。问题是,你能接受吗?如果你的程序在
    initialized
    false
    时确实抛出了一个异常,并且没有执行任何其他操作,那么答案可能是“是的,在使
    initialized
    变量
    volatile
    ”之后。在使用上下文之外询问这些方法是否“安全”是毫无意义的。@dasblinkenlight,是的,methodA将抛出异常。如果initialized是volatile,我认为它应该是线程safe@performanceuser我想问题是:如果init已经在运行但还没有完成,methodA抛出异常可以吗?如果可以,那么volatile就是您所需要的。如果没有,那么您需要描述当init已启动但尚未完成时methodA将要做什么。@performanceuser它不会是线程安全的,但后果将非常轻微,您可以安全地忽略这一事实。如果我将volatile添加到initialized中,为什么它直到现在都不是线程安全的?你能解释一下吗?@performanceuser-如果
    init()
    initialized
    所做的一切都是在开始时测试它,然后在结束时写入它,那么方法本身就不需要同步,你可以使用
    volatile
    。(如果可以从多个线程调用
    init()
    本身,那么它仍然需要同步。)我链接到的Goetz文章中非常详细地描述了用于此分析的确切因素。
    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()
            }
        }
    }