Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does explicit lock automatically provide memory visibility?

Sample code:

class Sample{
    private int v;
    public void setV(){
        Lock a=new Lock();
        a.lock();
        try{
            v=1;
        }finally{
            a.unlock();
        }
    }
    public int getV(){
        return v;
    }
}

If I have a thread constantly invoke getV and I just do setV once in another thread, Is that reading thread guaranteed to see the new value right after writing? Or do I need to make "V" volatile or AtomicReference?

If the answer is no, then should I change it into:

class Sample{
    private int v;
    private Lock a=new Lock();
    public void setV(){
        a.lock();
        try{
            v=1;
        }finally{
            a.unlock();
        }
    }
    public int getV(){
        a.lock();
        try{
            int r=v;
        }finally{
            a.unlock();
        }
        return r;
    }
}
like image 779
Temple Wing Avatar asked Sep 14 '12 18:09

Temple Wing


People also ask

What is monitor lock in Java threads?

A lock typically prevents more than one entity from accessing a shared resource. Each object in the Java language has an associated lock, also referred to as a monitor, which a thread obtains by using a synchronized method or block of code.

What is implicit lock in Java?

Implicit locks are automatically acquired by the server to ensure data integrity among multiple users. To allow greatest concurrency, the server acquires locks only when needed and frees them as soon as it can.


2 Answers

From the documentation:

All Lock implementations must enforce the same memory synchronization semantics as provided by the built-in monitor lock:

  • A successful lock operation acts like a successful monitorEnter action
  • A successful unlock operation acts like a successful monitorExit action

If you use Lock in both threads (i.e. the reading and the writing ones), the reading thread will see the new value, because monitorEnter flushes the cache. Otherwise, you need to declare the variable volatile to force a read from memory in the reading thread.

like image 60
Sergey Kalinichenko Avatar answered Oct 12 '22 10:10

Sergey Kalinichenko


As per Brian's Law...

If you are writing a variable that might next be read by another thread, or reading a variable that might have last been written by another thread, you must use synchronization, and further, both the reader and the writer must synchronize using the same monitor lock.

So it would be appropriate to synchronize both the setter and getter......

Or

Use AtomicInteger.incrementAndGet() instead if you want to avoid the lock-unlock block (ie. synchronized block)

like image 21
Kumar Vivek Mitra Avatar answered Oct 12 '22 11:10

Kumar Vivek Mitra