In Java, the happened before semantic ensure that visibility.
For example, node.setPrevRelaxed(t) is used in two place, the first one is in the enqueue method
final void enqueue(Node node) {
if (node != null) {
for (;;) {
Node t = tail;
node.setPrevRelaxed(t); // avoid unnecessary fence
if (t == null) // initialize
tryInitializeHead();
else if (casTail(t, node)) {
t.next = node;
if (t.status < 0) // wake up to clean link
LockSupport.unpark(node.waiter);
break;
}
}
}
}
node != null iff euqueue is call in Condition object which ensure this object has acquired a lock.
Another place is in acquire method
...
node.waiter = current;
Node t = tail;
node.setPrevRelaxed(t); // avoid unnecessary fence
if (t == null)
tryInitializeHead();
else if (!casTail(t, node))
node.setPrevRelaxed(null); // back out
else
t.next = node;
...
In theses two case, the node.prev will be seen after the lock is released or casTail successfully.