在二叉树中,我试图以原子方式将父节点的左子节点替换为新节点。
在下面的方法中,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);
}
答案 0 :(得分:1)
您的问题(以及标记为java
和c
的事实)表明您来自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");
我使用
进行CASc0Update.compareAndSet(pending.p, pending.l, pending.newChild)
除了手动展开数组元素之外,我还有一种简单的方法吗?