我正在设置一个标志,该标志由任何设置它的线程设置一次。所有其他线程将在不同的时间,经常读取此标志重复。
现在我正在使用AtomicBoolean,它运行正常,但我知道如果经常查询它可能比普通布尔慢得多(不确定这是否正确)。
将此更改为静态布尔值是否可以线程安全?无论谁做到这一点,都将标志设置为true,实际上可以允许所有这些标志多次设置标志。
我关心的是阅读旗帜的人能够多快发现它?这是对的吗?或者他们可能没有做对吗?
此外,使用经常查询的AtomicBoolean的性能有多大?
另外,我是否应该考虑在AtomicBoolean上使用volatile布尔值,因为我几乎只需要设置一次并读取它,并且可以原子地执行set操作(在AtomicBoolean中复制getAndSet()的代码)
答案 0 :(得分:2)
如果一个线程设置了值而其他线程读取了它,则volatile可以正常工作。
如果许多线程可能将其设置为true而您不关心哪一个实际执行它,然后其他线程只读它,volatile也可以正常工作。
如果许多线程可能将其设置为true / false,那么原子或同步或某种锁结构是唯一的方法。
是的,存在原子,同步等的性能问题。但安全性通常超过这个。
答案 1 :(得分:2)
当大多数线程只读取变量并且只读取其中一个并且一次更改该值时,您不必担心性能。 AtomicBoolean正在使用一种名为CAS的机制,现在大多数现代处理器都支持它,并且是一种低级操作。使用CAS的结果是,在读取值时几乎没有任何缺点(这与使用标准锁不同)。使用你描述的volatile静态布尔方案就足够了 - volatile可以防止jvm在从变量读取时进行优化,比如重用寄存器中保存的值而不是检查内存中的值,所以每当一个线程改变变量的值时,其他线程就会看到改变。在您的情况下,两种解决方案都会给出相似但性能相同的结果。 在很多写操作的情况下,Volatile会比AtomicBoolean更快,但老实说,我无法想象你有很多写作的情况,没有人有兴趣阅读。
答案 2 :(得分:0)
如果变量仅由任何线程设置一次并且以后永远不会更改,则可以使用条件同步块通过消除不必要的同步调用来获得一些性能。
但我认为不值得做。只需使用AtomicBoolean或volatile变量。
public class Sandbox1 {
private boolean status;
public void setStatus(boolean status) {
if (!this.status) {
synchronized (this) {
this.status = status;
}
}
}
public boolean isStatus() {
if (!this.status) {
synchronized(this) {
return this.status;
}
}
return this.status;
}
}