【问题标题】:AtomicInteger conditional check thread safeAtomicInteger 条件检查线程安全
【发布时间】:2018-01-17 20:23:32
【问题描述】:

我怀疑下面是否是线程安全的,

// is this thread safe, final int MAX_COUNT = 3 ?
if (retryCount.get() < MAX_COUNT) {
    // some other code
    retryCount.getAndIncrement();
} else {
    // reset count & some other code
    retryCount.set(0);
}

上面的条件检查线程安全吗?

【问题讨论】:

    标签: java multithreading atomicinteger


    【解决方案1】:

    不,它没有。

    假设两个线程 T1T2retryCount 实际上包含 2 值。
    假设T1 执行if(retryCount.get() &lt; MAX_COUNT){(评估为真)但没有达到retryCount.getAndIncrement();
    T1 被暂停。 T2 被恢复。
    T2 执行 if(retryCount.get() &lt; MAX_COUNT){ 仍被评估为真。

    所以您确定retryCount 的值将等于4

    您需要显式同步,在这种情况下 AtomicInteger 可能不需要:

    synchronized(lock){
      if(retryCount.get() < MAX_COUNT){
      // some other code
      retryCount.getAndIncrement();
      }else{
       // reset count & some other code
       retryCount.set(0);
      } 
    }
    

    【讨论】:

    • 也可以使用retryCount.getAndUpdate(i -&gt; (i + 1) % (MAX_COUNT + 1))
    • @Bubletan 您省略了“其他代码”部分。
    • @matt 好吧,我确实假设其他代码可以按任何顺序执行。
    • @Bubletan 的示例可以扩展到if(retryCount.updateAndGet(i -&gt; (i + 1) % (MAX_COUNT + 1)) != 0) { /* code for ordinary case */ } else { /* code when resetting */ },如果这不合适,即“其他代码”的顺序和计数器更新很重要,那么AtomicInteger 不是适合该工作的工具.到那时,对retryCount 和任何“其他代码”修改的所有其他访问也需要同步(在同一个锁上)......
    【解决方案2】:

    不,它不是线程安全的,因为代码正在执行所谓的check-then-act 操作。

    AtomicInteger 本身是线程安全的,这意味着它的各个方法是原子的,但执行复合操作不是原子的。所以上面的代码需要同步

    这里有一些来自 Java Concurrency In Practice 的精彩笔记

    【讨论】:

      猜你喜欢
      • 2021-08-25
      • 1970-01-01
      • 2019-10-06
      • 2016-04-20
      • 2012-04-14
      • 2013-08-29
      • 2016-12-06
      • 2013-01-31
      • 1970-01-01
      相关资源
      最近更新 更多