The problem is that your no-arg constructor calls setValue(...) for the newly created instance:
public StackNode() { setValue(null); setNext(null); }
and your Runnable setValue creates a new StackNode instance to go to node.setNext(...) :
node.setNext(new StackNode());
(even if your test never uses node.next , so this is essentially non-op aside from the result they output). Because synchronized methods are instance methods (not static ), they have separate locks, which means that the call to setValue(...) in the new instance constructors is not synchronized with the calls you make to node .
Please note that although your specific problem is rather unusual (you have a getter and setter that control the overall external state, namely System.out , but do not have corresponding common locks to prevent interference), it is actually always a bad idea to call a method from the designer, unless the method is not private or final or static , or class final , because the superclass constructor is called before the subclass instance will be fully established, therefore, if the constructor is a method that is overridden in conn Behold, the subclass method will receive an incomplete object this and can be terribly mistaken. You better change your constructor to this:
public StackNode() { value = null; next = null; }
(or just remove the assignment instructions altogether, since fields of the reference type are automatically initialized to null ).
source share