![](/img/trans.png)
[英]AtomicBoolean guard for not thread-safe data (volatile piggybacking)
[英]Thread-safe negated AtomicBoolean get() as a condition in a while loop
假设我有以下代码:
AtomicBoolean condition;
condition = new AtomicBoolean(false);
(...)
while(!condition.get()){
// do some stuff
}
我知道condition.get()
是原子的 ,但是,还是!condition.get()
原子?
我的意思是,如果一个Thread
以原子方式读取布尔值,然后在应用之前中断它就会发生!
操作,以便另一个Thread
进入循环之前? 如果是这种情况,使用如下函数会更好吗:
private synchronized boolean checkNegatedCondition(AtomicBoolean cond){
return !cond.get();
}
(...)
while(checkNegatedCondition(condition)){
// do some stuff
}
提前致谢。
一个必须在这里准确:
get()
操作的结果应该是原子的,并且由于对任何原子类的“进一步”保证,它也保证对于查看同一对象的其他线程是“可见的”(在某种意义上说是原子的)所有** set *方法都是原子的 ,因此不可能get()
“半集”的东西) 而且可以肯定:这里的核心问题不是 “原子性” - 因为get()
只返回一个值(与double相反,甚至只有一个位/字节受影响)。 换句话说: AtomicBoolean
主要是为了确保使用该对象的所有线程都可以看到对象的更改。
但是,是的, 假设 AtomicBoolean是一个类的字段 ,并且多个线程正在调用如下方法:
public void foo() {
while(!condition.get() ...
从理论上讲 ,这是可能的
但是:假设我们有一个“受保护的” getNot()
,最终结果将是相同的 :
在这两种情况下,第一个线程都会进入循环!
原子性不是问题。 两个线程可以同时读取原子变量。 因此,任何数量的线程都可以读取该值并根据其否定进入循环。 如果没关系! 是原子的。 它作用于线程本地值。
要使用原子进行排除,通常需要AtomicBoolean.compareAndSet(boolean,boolean)
。
v.compareAndSet(a,b)
只会将v
设置为值b
如果它是a
并返回true。 否则如果v在开始时没有值a
,则它什么都不做并返回false。
在伪代码中它是
synchronized public boolean compareAndSet(boolean a,boolean b){
if(v!=a) return false;
v=b;
return true;
}
但是(非常重要)以原子方式进行,因此v上的所有其他操作可以在它之前或之后进行排序。
AtomicBoolean condition = new AtomicBoolean(false);
//...
if(condition.compareAndSet(false,true)){
//Only one thread can get here unless condition is set back...
}
如果你想将它用作'伪'同步块,你可能会编码:
while(!condition.compareAndSet(false,true));
//Only one thread can get here at a time...
condition.set(false);
这可以被描述为'锁定'。 因为线程'等待'进入受控部分'旋转'在循环中四舍五入直到释放。 这可能表现出比synchronized
更差的性能,因为该操作系统通常会“暂停”等待线程并执行其他任务。 然而,在争用非常低的情况下(即需要很少或不需要等待),自旋锁可以表现出更好的性能。
Pro-Tip:在实践中,最好将condition.set(false) in a
finally`块中:
while(!condition.compareAndSet(false,true));
try {
//Only one thread can get here at a time...
}finally{
condition.set(false);
}
否则,在一个线程中抛出的异常将永久lock out
对该部分代码的任何访问。
AtomicBoolean.get不是关于原子的,而是关于线程安全的。
原子将是一个与读写东西相关的概念,你的问题没有提到这样的东西。
如果你想原子地读写(或写和读),AtomicBoolean上有其他方法(比如getAndSet或compareAndSet)。 从您的问题看,您可能正在寻找与此更相关的内容(无法从您的问题详细信息中确定)。
如果您想要的不是以原子方式检索和更改值,而是检索直到在某些逻辑之后在代码的其他位置更改它(因此不是原子地),那么您正在寻找锁定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.