在多线程环境中有两个重要的概念。
原子
能见度
Volatile解决了可见性问题,但它不涉及原子性,例如:我++。在这里,i ++不是一个单一的机器指令,而是三个机器指令。
将值复制到注册
增加它
放回去
AtomicInteger,AtomicReference基于比较和交换指令。 CAS有三个操作数,一个操作的存储位置V,预期的旧值A和新的值B.CAS原子地将V更新为新的值B,但前提是V中的值与预期的旧值A匹配;否则它什么都不做。在任何一种情况下,它都返回当前V中的值。这由JVM在AtomicInteger,AtomicReference中使用,如果底层处理器不支持此功能,则它们将函数调用为compareAndSet(),然后JVM通过自旋锁实现它。
Set是原子的(它并不总是正确的)但是比较然后设置不是原子的。所以当你有这个要求时,例如当值为X然后只更改为Y所以要原子地执行此操作您需要这种基元,您可以使用AtomicInteger,AtomicReference的compareAndSet,例如atomicLong.compareAndSet(long expect, long update)
您实际上可以使用此原语来开发强大的数据结构,如并发堆栈。
import java.util.concurrent.atomic.AtomicReference;
public class MyConcurrentStack {
private AtomicReference head = new AtomicReference();
public MyConcurrentStack() {
}
public void push(T t) {
if (t == null) {
return;
}
Node n = new Node(t);
Node current;
do {
current = head.get();
n.setNext(current);
} while (!head.compareAndSet(current, n));
}
public T pop() {
Node currentHead = null;
Node futureHead = null;
do {
currentHead = head.get();
if (currentHead == null) {
return null;
}
futureHead = currentHead.next;
} while (!head.compareAndSet(currentHead, futureHead));
return currentHead.data;
}
/**
*
* @return null if no element present else return a element. it does not
* remove the element from the stack.
*/
public T peek() {
Node n = head.get();
if (n == null) {
return null;
} else {
return n.data;
}
}
public boolean isEmpty() {
if (head.get() == null) {
return true;
}
return false;
}
private static class Node {
private final T data;
private Node next;
private Node(T data) {
this.data = data;
}
private void setNext(Node next) {
this.next = next;
}
}
}