0

In a binary tree, I'm trying to atomically replace left child of parent to a new node. In the below method, pnode.left is pointing to node and I'm trying to change it to replaceNode.

In line1, childPtr is pointing to pnode.left
In line2, oldChildPtr is pointing to pnode.left
In line3, childPtr is atomically changed from pointing topnode.left to replaceNode.

But pnode.left is unchanged. I understand that this is how things work in java. But how do I modify this code so that pnode.left is atomically replaced with replaceNode.

atomicReplaceLeftChild(node,pnode,replaceNode)
{
    AtomicReference<Node> childPtr = new AtomicReference<Node>(pnode.left);
    Node oldChildPtr = childPtr.get();
    childPtr.compareAndSet(oldChildPtr, replaceNode);
}
arunmoezhi
  • 3,082
  • 6
  • 35
  • 54

2 Answers2

1

Your question (aand the fact that it is tagged with both java and c) suggests you are coming from a C background. Nothing wrong with this, but I believe your concept of 'atomic' in a Java sense is not what you think it is. The Atomic* classes in java.util.concurrent package use internal locking mechanisms to ensure that the values in them cannot be partially completed before another thread gets access to them. Just because you use an Atomic* class in your code does not mean that your code does an atomic operation.

Your three lines of code are 'odd' and do not appear to represent a real use case. I say this because the code does not do anything. It creates an AtomicReference instance, and it messes with the referenced value, but it does nothing to change anything on pnode which is what I thought you were trying to do....

So, at some point you need to have pnode.left = replaceNode. It is possible that you may want pnode.left to actually be an AtomicReference itself, in which case it would be: pnode.left.compareAndSet(oldChildPtr, replaceNode)

In it's current state your code does not do much of any significance, and certainly does not do what you describe it should do.

Hope this does not discourage you.... assuming you are new to Java I don't envy you having to start off on Atomics and concurrency.... there are easier places to start.

rolfl
  • 17,539
  • 7
  • 42
  • 76
  • Thanks for the response. I understand my code is not doing anything. That is why in my question I said "But pnode.left is unchanged". I can do what you suggested. `pnode.left.compareAndSet(oldChildPtr, replaceNode)`. But then `pnode.left`has to be of type `AtomicReference` instead of `Node` – arunmoezhi Oct 30 '13 at 07:19
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");

I do a CAS by using

c0Update.compareAndSet(pending.p, pending.l, pending.newChild)

I there a easy way to do it other than manually unrolling the array elements?

arunmoezhi
  • 3,082
  • 6
  • 35
  • 54