volatile variables and memory barrier in java

梦想与她 提交于 2019-12-02 21:15:29

1.

Based on what you say here

constructing a new object, setting its fields and setting the next field to the object pointed by the root, then setting the root's next field to this new node.

Then yes, setting the next field to volatile will correctly synchronize. Its important to understand why. You have three sets of writes before hand, the one to the node object, one to the fields and one to the nodes next (though not completely sure why you are doing that, maybe I miss understand something).

So that's 2 + (N number of field) writes. At this point there is no happens-before relationship and if the node is written normally there is no guarantee. As soon as you write to the volatile field all previous writes will now also be visible.

2.

Volatile reads/writes on a x86 (or any cache-coherent) operating system has the following attributes:

 volatile-read: very close to a normal read
 volatile-write: about 1/3 the time of a synchronization write 
         (whether within intrinsic locking or  j.u.c.Lock locking)

3.

Looks like you will have to create VolatileNode and Node. There was a proposal for Java 7 to come out with a Fences API which you can specify which style of reading/write you want to execute with a static utility class but doesn't look like its releasing

Edit:

Thkala made a great point I feel is worth including

although it should be pointed out that pre-JSR133 JVMs (i.e. Java < 5.0) did not have the same semantics

So what I wrote does not apply to applications run in Java 1.4 or less.

Making the next field volatile would impose a memory barrier on all instances of the node class, not just the root node. I'd expect that to be more expensive than just using synchronized on the root node. In addition, the JVM may be able to optimize synchronized method calls far better. See also this and this.

That said, you should probably try both and benchmark/profile to see what happens.

Your root node actually does not need to be a node. You only need a reference to the first "real" node.

public class LinkedList {
  private volatile Node firstNode;
  ...
  addNode(Node node) {
    node.next = firstNode;
    firstNode = node;
  }
}

So you don't need to make the next field volatile in all your nodes; the nodes are not synchronized at all. You could use that class for the non-synchronized linked lists if you don't mind the cost of the volatile access to the first node. Or you could instead simply rewrite the class with a non-volatile firstNode for the non-synchronized version.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!