【问题标题】:Atomic boolean, test for current value原子布尔值,测试当前值
【发布时间】:2015-02-24 14:17:29
【问题描述】:

我无法理解 AtomicBoolean 以及如何充分利用它的方法 getAndSet(boolean newValue);

Volatile 直接在内存中进行所有更改,因此如果 CPU 无法缓存某些值,则可以保证线程之间的更改可见性。 同步保护免受竞争条件的影响。

以下代码线程安全吗? AtomicBoolean.get 应该提供 volatile 保证,但是竞态条件呢?

private static AtomicBoolean tokenValid = new AtomicBoolean(false); 
   //....

    public non-synchronized method() { 

    if (token == null || tokenValid.getAndSet(tokenValid.get()) == false) 

           token = createNewToken()

 }

我知道有很多关于 Atomic 类的资源,但是我没有找到这样的示例,这可能表明我在滥用 AtomicBoolean。

【问题讨论】:

  • 当我们不知道您想要达到的目标时,很难说它是否安全。如果你只是想获取当前值,tokenValid.get() 有什么问题?
  • 我不认为代码是逻辑安全的。你想用它来达到什么目的?
  • 如果我尝试执行 tokenValid.get 而其他一些线程尝试执行 set 会发生什么?我想做什么:如果不满足上述条件,请获取一些新令牌。如果满足条件并且我只想获得一次令牌,则可以同时测试一个以上的线程
  • 什么是token,你为什么要检查它是否是null?您是否了解并发问题是什么以及为什么 getAndSet() 应该防止它?
  • 此外,以“缓存刷新/无效”的简单术语来推理 volatile 的语义不会让您正确了解 Java 内存模型。这些不是理解发生在概念的可行捷径。

标签: java multithreading atomic


【解决方案1】:

没有。您的代码不是线程安全的。 AtomicBoolean 方法本身是线程安全的并且避免了竞争条件,但是在对这些方法的调用之间仍然可以有其他线程访问该对象。在您的情况下,首先调用 tokenValid.get(),然后调用 tokenValid.getAndSet(boolean)。在这两个调用之间,其他线程可能会调用tokenValid 的方法之一。

更不用说您还访问了token 变量,并且不清楚它是成员变量(其他线程可能访问)还是局部变量(不是)。

【讨论】:

  • 那么,如果我做了 tokenValid.getAndSet(true) 那么它是线程安全的吗?暂时搁置令牌对象。
  • @user3360241。就tokenValid 而言,是的。如果另一个线程执行tokenValid.getAndSet(true),则在其中一个线程中返回true,在另一个线程中返回tokenValid 的旧值。不会发生两个线程都看到旧值然后都将值设置为 true 的情况。
猜你喜欢
  • 2017-11-24
  • 2011-01-04
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
  • 2021-12-27
  • 2017-09-27
  • 2013-02-09
  • 1970-01-01
相关资源
最近更新 更多