Answers:
当有多个线程需要检查并更改布尔值时。例如:
if (!initialized) {
initialize();
initialized = true;
}
这不是线程安全的。您可以使用AtomicBoolean
以下方法修复它:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
何时initialize()
尚未完成。因此,仅当其他线程不关心的完成时它才起作用initialize()
。
initialized
仅用于确保只有一个线程将调用该initialize()
方法,那么我认为这是一个完全有效的真实示例。显然initialized
是真实的,并不意味着初始化在这种情况下,肯定完成,所以也许稍有不同的任期将是更好地在这里。同样,这取决于它的用途。
volatile boolean
与AtomicBoolean
?不相同。
synchronized
块,在这种情况下,您不再需要AtomicBoolean
,而只需一个volatile boolean
。(if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
将确保只有一个线程被调用initialize
,并且确保所有其他线程都已等待它进行调用,前提是initialized
已标记volatile
。)
这是我做的笔记(摘自Brian Goetz的书),可能对您有帮助
AtomicXXX类
提供无阻塞的比较和交换实现
充分利用硬件提供的支持(Intel上的CMPXCHG指令)当大量线程正在使用这些原子并发API的代码中运行时,它们的伸缩性将比使用对象级监视器/同步的代码好得多。由于Java的同步机制使代码处于等待状态,因此当关键部分中运行大量线程时,将花费大量CPU时间来管理同步机制本身(等待,通知等)。由于新的API使用硬件级别的构造(原子变量)以及无需等待和锁定的算法来实现线程安全,因此“做某事”而不是在管理同步上花费了大量的CPU时间。
不仅可以提供更好的吞吐量,而且还可以更好地抵御死锁和优先级反转等活动问题。
可以使用原子布尔的两个主要原因。首先,它是可变的,您可以将其作为参考传递,并更改与布尔值本身关联的值。
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,则必须通过声明其易失性或在字段的读写周围进行同步来同步所使用的布尔变量。
该AtomicBoolean
班为您提供了一个布尔值,你可以原子更新。当有多个线程访问布尔变量时使用它。
在java.util.concurrent.atomic包概述给你的东西在这个包中的类做和何时使用它们好高层次的描述。我还会推荐Brian Goetz 撰写的《Java Concurrency in Practice》一书。
包装说明摘录
软件包java.util.concurrent.atomic的描述:类的小型工具包,支持对单个变量进行无锁线程安全编程。[...]
这些方法的规范使实现能够采用当代处理器上可用的高效机器级原子指令。
类AtomicBoolean,AtomicInteger,AtomicLong和AtomicReference的实例各自提供对相应类型的单个变量的访问和更新。[...]
原子访问和更新的记忆效应通常遵循挥发物的规则:
- get具有读取易失性变量的存储效果。
- set具有写入(分配)volatile变量的存储效果。
- weakCompareAndSet以原子方式读取和有条件地写入变量,相对于该变量上的其他内存操作而言是有序的,否则将用作普通的非易失性内存操作。
- compareAndSet和所有其他读取和更新操作(如getAndIncrement)具有读取和写入易失性变量的内存影响。
volatile boolean
VSAtomicBoolean
:stackoverflow.com/questions/3786825/...