mik*_*era 4 java concurrency atomic
我正在尝试使用java.util.concurrent并试图找出如何正确使用AtomicReference.compareAndSet来管理对单个共享状态单元的并发访问.
特别是:compareAndSet的以下用法是否正确且安全?任何陷阱?
我的测试类是一个基于链接节点列表的简单堆栈.
public class LinkedStack<T> {
AtomicReference<Node<T>> topOfStack=new AtomicReference<Node<T>>();
public T push(T e) {
while(true) {
Node<T> oldTop=topOfStack.get();
Node<T> newTop=new Node<T>(e,oldTop);
if (topOfStack.compareAndSet(oldTop, newTop)) break;
}
return e;
}
public T pop() {
while(true) {
Node<T> oldTop=topOfStack.get();
if (oldTop==null) throw new EmptyStackException();
Node<T> newTop=oldTop.next;
if (topOfStack.compareAndSet(oldTop, newTop)) return oldTop.object;
}
}
private static final class Node<T> {
final T object;
final Node<T> next;
private Node (T object, Node<T> next) {
this.object=object;
this.next=next;
}
}
...................
}
Run Code Online (Sandbox Code Playgroud)
是的,这正是应该如何使用的.
也许以下语法会更优雅:
Node<T> oldTop = null;
Node<T> newTop = null;
do {
oldTop=topOfStack.get();
newTop=new Node<T>(e,oldTop);
} while (!topOfStack.compareAndSet(oldTop, newTop));
Run Code Online (Sandbox Code Playgroud)
它目前的形式是正确的。
您的结构称为 Treiber 堆栈。它是一种简单的线程安全无锁结构,但存在单点争用 ( topOfStack) 的问题,因此往往会严重扩展(在争用情况下,它会崩溃,这与 MMU 的配合不太好)。如果争用可能较低但仍需要线程安全,那么这是一个不错的选择。
有关扩展堆栈算法的进一步阅读,请参阅 Danny Hendler、Nir Shavit 和 Lena Yerushalmi 撰写的“可扩展无锁堆栈算法 (pdf) ”。
| 归档时间: |
|
| 查看次数: |
3303 次 |
| 最近记录: |