假设我有以下代码:
AtomicBoolean condition;
condition = new AtomicBoolean(false);
(...)
while(!condition.get()){
// do some stuff
}
我知道condition.get()
是atomic,但是!condition.get()
也是原子的吗?
我的意思是,是否会发生一个Thread
原子地读取布尔值然后在应用!
操作之前被中断,以便另一个Thread
进入循环之前?如果是这种情况,那么使用诸如以下的函数会更好吗
private synchronized boolean checkNegatedCondition(AtomicBoolean cond){
return !cond.get();
}
(...)
while(checkNegatedCondition(condition)){
// do some stuff
}
提前致谢。
答案 0 :(得分:4)
这里必须准确无误:
get()
操作的结果应该是原子的,因为"进一步"任何原子类的保证,也保证可见"可见"查看同一个对象的其他线程(所有** set *方法都是 atomic 的意义上的原子,因此不可能get()
某事那是"半套")只是为了确定:这里的核心是不"原子性" - 因为get()
只返回一个值(与double相反,甚至只有一个位/字节受影响)。换句话说:AtomicBoolean
主要是确保使用该对象对所有线程可以看到对象的更改。
但是,假设 AtomicBoolean 是一个类的字段,并且多个线程正在调用类似的方法:
public void foo() {
while(!condition.get() ...
理论上可能
但是:假设我们有一个受保护的" getNot()
,最终结果将是相同:
在这两种情况下,第一个线程都会进入循环!
答案 1 :(得分:3)
原子性不是问题。 两个线程可以同时读取原子变量。 因此,任何数量的线程都可以读取该值并根据其否定进入循环。如果没关系!是原子的。它作用于线程本地值。
要使用原子进行排除,通常需要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
更差的性能,因为该操作系统通常会“暂停”等待线程并执行其他任务。
但是,在争用率很低的情况下(即很少或不需要等待),自旋锁可以表现出更好的性能。
专业提示:在实践中,最好将condition.set(false) in a
最终阻止:
while(!condition.compareAndSet(false,true));
try {
//Only one thread can get here at a time...
}finally{
condition.set(false);
}
否则,在一个线程中抛出的异常将永久lock out
对该段代码的任何访问。
答案 2 :(得分:0)
AtomicBoolean.get不是关于原子的,而是关于线程安全的。
atomic将是一个与读写内容相关的概念,而你的问题并未提及类似内容。
如果要以原子方式读写(或写入和读取),AtomicBoolean上还有其他方法(如getAndSet或compareAndSet)。从您的问题看,您似乎正在寻找与此更相关的内容(无法从您的问题详细信息中确定)。
如果您想要的不是以原子方式检索和更改值,而是检索直到在某些逻辑之后在代码的其他位置更改它(因此不是原子地),那么您正在寻找锁定。