Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to synchronize or lock upon variables in Java?

Let me use this small and simple sample:

class Sample {     private String msg = null;      public void newmsg(String x){         msg = x;     }      public String getmsg(){         String temp = msg;         msg = null;         return temp;     } } 

Let's assume the function newmsg() is called by other threads that I don't have access to.

I want to use the synchonize method to guarantee that the string msg is only used by one function per time. In other words, function newmsg() cannot run at the same time as getmsg().

like image 904
Winter Avatar asked May 02 '11 20:05

Winter


People also ask

How do you synchronize variables in Java?

To make this code properly synchronized in Java you need to either make both method static or nonstatic or use java synchronized block instead of java synchronized method. By the way, this is one of the common mistake Java developers make while synchronizing their code.

What is difference between lock and synchronization in Java?

Major difference between lock and synchronized: with locks, you can release and acquire the locks in any order. with synchronized, you can release the locks only in the order it was acquired.

What is synchronized lock in Java?

When we use a synchronized block, Java internally uses a monitor, also known as monitor lock or intrinsic lock, to provide synchronization. These monitors are bound to an object; therefore, all synchronized blocks of the same object can have only one thread executing them at the same time.

Which lock is used for synchronized method?

When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.


2 Answers

That's pretty easy:

class Sample {     private String message = null;     private final Object lock = new Object();      public void newMessage(String x) {         synchronized (lock) {             message = x;         }     }      public String getMessage() {         synchronized (lock) {             String temp = message;             message = null;             return temp;         }     } } 

Note that I didn't either make the methods themselves synchronized or synchronize on this. I firmly believe that it's a good idea to only acquire locks on objects which only your code has access to, unless you're deliberately exposing the lock. It makes it a lot easier to reassure yourself that nothing else is going to acquire locks in a different order to your code, etc.

like image 134
Jon Skeet Avatar answered Sep 28 '22 10:09

Jon Skeet


For this functionality you are better off not using a lock at all. Try an AtomicReference.

public class Sample {     private final AtomicReference<String> msg = new AtomicReference<String>();      public void setMsg(String x) {         msg.set(x);     }      public String getMsg() {         return msg.getAndSet(null);     } } 

No locks required and the code is simpler IMHO. In any case, it uses a standard construct which does what you want.

like image 40
Peter Lawrey Avatar answered Sep 28 '22 08:09

Peter Lawrey