繁体   English   中英

使用 final 的线程安全

[英]Thread Safety using final

下面是一个解释线程安全的示例方法:

class Counter {
    private int counter = 0;

    public void increment() {
        counter++;
    }

    public int getValue() {
        return counter;
    }
}

为了提供线程安全,有几种方法,我更喜欢使用AtomicInteger方法。 然而;

1.我还想知道是否可以通过对必要的变量使用final来提供线程安全。 如果是这样,我该如何执行此操作?

2.在 Java 中经常使用final作为变量和方法 arguments 提供线程安全的原因之一是什么?

我只是将这个添加到 Erwan Daniel 的回答中。
如果您想在所有线程之间共享一个计数器,这里是您的代码的另一个版本。

 class SharedCounter {
  private AtomicInteger sharedCounter ;
  
  public Counter(){
   this.sharedCounter = new AtomicInteger(0);
  }

  public void increment() {
     sharedCounter.getAndIncrement();
  }

  public int value() {
     return sharedCounter.get();
  }

最终将阻止您的atomicInteger12更改它正在使用的object您可以自由设置它的值。

final SharedCounter atomicInteger12 = new Counter() ;

在正确同步的代码中,不需要final。

例如,如果你会使用:

class MyCounter{
    private AtomicInteger c = new AtomicInteger();

    public int inc(){return c.incrementAndGet();}

    public int get(){return c.get();}
}

您将与另一个线程共享“MyCounter”,您需要确保在写入 c 和读取 c 之间存在先发优势。 这可以通过各种方式完成,例如将 MyCounter 实例传递给某个线程的构造函数(线程启动规则)。 或者您通过 volatile 字段(volatile 变量规则)或同步块(监视器锁定规则)传递数据。

这通常称为“安全发布”,对于大多数系统来说,这已经足够了。 如果您没有安全地通过引用,您就会遇到数据竞争,并且可能会发生奇怪的问题。 因此有第二种机制称为初始化安全; 因此,无论对 object 的引用是否未正确发布,使用 final 的初始化安全都将作为备用解决方案。 此 AFAIK 的主要用例是安全性。

所以对于正确同步的代码,不需要final。

这并不意味着你可以忽略它。 它有各种各样的好处,比如没有意外的变化,而且信息量很大。 所以我更喜欢让尽可能多的字段成为final。

从 memory model 的角度来看,Final 对于方法 arguments 没有任何意义,因为它们是线程私有的。 只有共享的 memory 需要在 memory model 中处理。

不, final关键字与线程安全没有任何共同之处。

变量的final关键字使它们不可变,您不能再更改它们的值。 但是,它不像 c++ 中的const关键字,整个变量内容都不能改变。 在 Java 中,只有引用是不可变的。

   final AtomicReference<String> toto = new AtomicReference<>("text");
   toto.set("new text"); // totally fine
   toto = new AtomicReference<>("text"); // does not compile, as toto is immutable reference.

但是,还有另一个关键字可以满足您的需求。 它是volatile的。 https://www.baeldung.com/java-volatile

简而言之,所有线程上的值同时更改并且立即可用。 这就是所有Atomic* Java 类中使用的内容。

前任。 https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM