我如何使用AtomicBoolean以及该类的用途是什么?
答案 0 :(得分:207)
当多个线程需要检查并更改布尔值时。例如:
if (!initialized) {
initialize();
initialized = true;
}
这不是线程安全的。您可以使用AtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
答案 1 :(得分:47)
以下是我制作的笔记(来自Brian Goetz book),可能对您有所帮助
AtomicXXX课程
提供无阻塞比较和交换实现
利用提供的支持 通过硬件(CMPXCHG指令 在英特尔)当很多线程 运行您使用的代码 这些原子并发API,他们 将比代码更好地扩展 它使用对象级别 监视器/同步。以来, Java的同步机制 当有很多时候让代码等待 穿过你的线程 关键部分,实质性的 花费的CPU时间 管理同步 机制本身(等待,通知, 等等)。由于新API使用硬件 级别构造(原子变量) 等待并锁定免费算法 实现线程安全,更多 CPU时间用于“做事” 而不是管理 同步。
不仅提供更好的服务 吞吐量,但他们也提供 对生命的抵抗力更大 死锁等问题 优先反转。
答案 2 :(得分:30)
有两个主要原因可以使用原子布尔值。首先它是可变的,你可以将它作为引用传递,并改变与布尔本身相关联的值,例如。
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
并在someObject类
中public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
更重要的是,它的线程安全并且可以向维护该类的开发人员指出,该变量应该被修改并从多个线程读取。如果你不使用AtomicBoolean,你必须通过声明它是volatile或者围绕字段的读写来同步你正在使用的布尔变量。
答案 3 :(得分:17)
AtomicBoolean
类为您提供了一个可以原子更新的布尔值。当多个线程访问布尔变量时使用它。
java.util.concurrent.atomic package overview为您提供了关于此包中的类以及何时使用它们的高级描述。我还推荐Brian Goetz的书Java Concurrency in Practice。
答案 4 :(得分:5)
包java.util.concurrent.atomic description:一个小型工具包,支持对单个变量进行无锁线程安全编程。[...]
这些方法的规范使实现能够采用当代处理器上可用的高效机器级原子指令。[...]
类的实例AtomicBoolean,AtomicInteger,AtomicLong和AtomicReference均提供对相应类型的单个变量的访问和更新。[...]
访问和更新原子的记忆效应通常遵循挥发性规则:
- get具有读取volatile变量的记忆效应。
- set具有写入(赋值)volatile变量的记忆效应。
- weakCompareAndSet以原子方式读取并有条件地写入变量,相对于该变量上的其他内存操作进行排序,但在其他方面充当普通的非易失性内存操作。
- compareAndSet和所有其他读取和更新操作(如getAndIncrement)都具有读取和写入volatile变量的内存效果。