0

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

在 line1 中,childPtr正在指向pnode.left
In line2,oldChildPtr正在指向pnode.left
In line3,childPtr从指向 到 原子地更改pnode.leftreplaceNode

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);
}
4

2 回答 2

1

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

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

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

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

希望这不会让您灰心……假设您是 Java 新手,我不羡慕您必须从原子和并发开始……有更容易的起点。

于 2013-10-30T04:38:33.777 回答
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)

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

于 2013-11-19T08:29:10.707 回答