【问题标题】:AtomicInteger and Compare operationsAtomicInteger 和比较操作
【发布时间】:2019-02-25 07:59:06
【问题描述】:

我正在尝试使用 AtomicInteger 变量作为锁。 所以,想知道下面发布的代码是否是线程安全的。我知道 incrementAndGet() 是一个原子操作。但是,我不确定后续的 '==' 操作是否也是原子的(如果值在我进行比较时增加到 2 会怎样。)。所以发布这个问题来听听你的想法。

private AtomicInteger count = new AtomicInteger(0); //Shared variable
private final int max = 1;

if(count.incrementAndGet() == max) {
  //Do something
}

【问题讨论】:

  • 也就是说,你正在重塑Semaphore

标签: java multithreading atomicinteger


【解决方案1】:

由于incrementAndGet() 是一个原子操作,所以最多一个线程会得到1 的结果(只要AtomicInteger 的值不小于1)。这是由 AtomicInteger 保证的。虽然实际的比较不是这个原子操作的一部分,但只有接收到1 的线程才会运行到if 块中。这是因为比较比较了int 类型的两个值:incrementAndGet()) 和max 的结果。 AtomicInteger 在其中不起作用,因为当 count 的内部状态发生变化时,原语 int 不会改变它的值。 tl;dr:您的代码相当于:

final int val = count.incrementAndGet(); // (it makes no difference if val is not 'final`)
if (val == max) {
    // ...
}

Java 提供了许多其他方法来实现线程安全(LockCountDownLatchSemaphore、...),但由于您指的是 AtomicInteger,我相信 AtomicInteger.compareAndSet() 更准确你问的是:

if (count.compareAndSet(0, 1)) {
    // executed if count == 0
    count.set(0);
}

【讨论】:

  • 现在清楚多了。我只想要一个线程来执行某些功能。因此,我正在检查计数。因为它保证只有一个线程会看到值 1,所以我可以放心地期望驻留在“if”条件中的逻辑是线程安全的。由于 incrementandGet() 的每个操作都会增加计数,因此只有一个线程读取值 1。所以,这回答了我的问题。谢谢史蒂芬。
猜你喜欢
  • 2015-12-14
  • 2021-09-19
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多