原子整数,long,布尔等用于对各个类型进行任何原子更新,因为当我们对它们执行任何操作时可能存在争用条件,例如++。但是,在可能存在这种竞争条件的情况下引用哪些不同情况?Java引用的竞态条件
最好的问候,
凯沙夫因为它们涉及
原子整数,long,布尔等用于对各个类型进行任何原子更新,因为当我们对它们执行任何操作时可能存在争用条件,例如++。但是,在可能存在这种竞争条件的情况下引用哪些不同情况?Java引用的竞态条件
最好的问候,
凯沙夫因为它们涉及
AFAIK引用不受竞态条件的影响,因为JVM保证引用更新是原子操作(不像例如更新long
,其中在两个不同的步骤中更新低4字节和高4字节)。正如SLaks指出的那样,唯一关键的情况是compareAndSet
,这本质上不是原子性的。这在本地引用中很少使用,但是当需要一次更新两个(或更多)逻辑上相关的变量时,它就是一个已知的习惯用语AtomicReference
。 实践中的Java并发,第15.3.1节发布了一个示例,使用AtomicReference
在一个原子操作中更新两个变量(存储在简单的类中)。
的主要原因为AtomicReference
存在 - 除了接口的一致性 - 是知名度和安全出版物。在这个意义上,原子变量是“更好的volatile
”。
操作,如++
受到竞争条件多谨慎操作(读取,增量,商店)。
设置参考(a = b
)是一项单一操作,因此不会受到竞争条件的限制。
参考类型的操作(a.someMethod()
)可以做他们想做的任何事情,可能会或可能不会受到竞争条件的影响。
为了学习目的,我使用AtomicReference编写了一个ConcurrentLinkQueue。
package concurrent.AtomicE;
import java.util.concurrent.atomic.AtomicReference;
public class ConcurrentLinkQueue<V> {
private final AtomicReference<Node> firstNodePointer = new AtomicReference<Node>();
public void fastOffer(final V data){
final Node<V> newNode = new Node<V>(data,Thread.currentThread().getName());
System.out.println(newNode);
AtomicReference<Node> pointer = firstNodePointer;
for(;;){
if(pointer.get() == null){
if(pointer.compareAndSet(null,newNode)){
return;
}
}
pointer = pointer.get().getNext();
}
}
private static class Node<V>{
private AtomicReference<Node> next = new AtomicReference<Node>();
private volatile V data = null;
private String threadName = "";
Node(V data1,String threadName){
this.data = data1;
this.threadName = threadName;
}
@Override
public String toString() {
return "threadName=" + threadName +
", data=" + data;
}
private AtomicReference<Node> getNext() {
return next;
}
private void setNext(AtomicReference<Node> next) {
this.next = next;
}
private V getData() {
return data;
}
private void setData(V data) {
this.data = data;
}
}
那么为什么我们有一个类的AtomicReference – keshav84 2010-09-19 12:56:24
@keshu:'compareAndSet'是受竞争情况,因为它涉及到两个操作。 – SLaks 2010-09-19 12:57:32