Question

Is it possible to use volatile variables to allow consistent write-only synchronisation?

This is the code:

public class Controller {

    Container cont = new Container();
    ...

    public Object get(){
        if(!cont.isLocked()){
            return cont.getObject(); //many threads can read at the same time
        }
        else synchronized(cont){
            return cont.getObject(); //threads wait until write is finished
        }
    }

    public void set(Object o){
        synchronized(cont){
            cont.lock();
            cont.setObject(o);
            cont.unlock();
        }
    }
}

public class Container {
    private volatile boolean lock = false;
    private Object data;

    public Container(){
            }

    public void lock() {
        lock = true;
    }

    public void unlock() {
        lock = false;
    }

    public boolean isLocked() {
        return lock;
    }

    public void setObject(Object o) {
        data = o;
    }

    public Object getObject() {
        return data;
    }
}

Will it work, or will it break, what do you think?

Was it helpful?

Solution

It may/will break. Example of execution:

  • T1: if(!cont.isLocked()) returns true
  • T2: set(someObject)
  • T1: return cont.getObject(); returns an old version

Even worse, since you don't have a proper happens-before relationship between T2 and T1, cont.getObject() may return the a reference to the new object created by T2, but pointing to an inconsistent/not-fully-constructed object.

You have a typical check-then-act problem.

Why don't you just use a volatile reference to your object?

public class Controller {

    private volatile Object obj = new Object();

    public Object get(){ return obj; }
    public void set(Object o){ obj = o; }
}

That would be thread safe.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top