Java compareAndSet以原子方式更新BST中的引用

时间:2013-10-30 03:11:48

标签: java c binary-search-tree java.util.concurrent compare-and-swap

在二叉树中,我试图以原子方式将父节点的左子节点替换为新节点。 在下面的方法中,pnode.left指向node,我正在尝试更改它 到replaceNode

在第1行中,childPtr指向pnode.left
在第2行中,oldChildPtr指向pnode.left
在第3行中,childPtr原子地从指向pnode.left变为replaceNode

但是pnode.left没有变化。我知道这就是java中的工作方式。 但是,如何修改此代码,以便将pnode.left原子替换为replaceNode

atomicReplaceLeftChild(node,pnode,replaceNode)
{
    AtomicReference<Node> childPtr = new AtomicReference<Node>(pnode.left);
    Node oldChildPtr = childPtr.get();
    childPtr.compareAndSet(oldChildPtr, replaceNode);
}

2 个答案:

答案 0 :(得分:1)

您的问题(以及标记为javac的事实)表明您来自C背景。没错,但我相信你在Java意义上的'原子'概念并不是你想象的那样。 Atomic*包中的java.util.concurrent类使用内部锁定机制来确保在另一个线程访问它们之前,它们中的值不能部分完成。仅仅因为您在代码中使用Atomic*类并不意味着您的代码执行原子操作。

您的三行代码是“奇怪的”,似乎并不代表真实的用例。我这样说是因为代码没有任何东西。它创建了一个AtomicReference实例,并且它与引用的值混淆,但它没有改变pnode上的任何内容,这是我认为你试图做的....

所以,在某些时候你需要pnode.left = replaceNode。您可能希望pnode.left实际上是AtomicReference本身,在这种情况下它将是:pnode.left.compareAndSet(oldChildPtr, replaceNode)

在它的当前状态下,你的代码没有任何重要意义,当然也没有你所描述的应该做的事情。

希望这不会让你气馁......假设你是Java的新手,我不羡慕你不得不开始使用Atomics和并发......有更容易开始的地方。

答案 1 :(得分:0)

static final AtomicReferenceFieldUpdater<Node, Node> c0Update = AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "c0");
static final AtomicReferenceFieldUpdater<Node, Node> c1Update = AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "c1");
static final AtomicReferenceFieldUpdater<Node, Node> c2Update = AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "c2");
static final AtomicReferenceFieldUpdater<Node, Node> c3Update = AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "c3");
static final AtomicReferenceFieldUpdater<Node, UpdateStep> infoUpdate = AtomicReferenceFieldUpdater.newUpdater(Node.class, UpdateStep.class, "pending");

我使用

进行CAS
c0Update.compareAndSet(pending.p, pending.l, pending.newChild)

除了手动展开数组元素之外,我还有一种简单的方法吗?