Using -Synchronized Methods
Synchronization is easy in Java, because all objects have their on implicit monitor associated with them. To enter an object’s monitor, just call a method that has been modified with the synchronized keyword. Whiic a thread is inside a synchronized method, all other threads that try to call it (or any other synchronized method) on the same instance have to wait. To exit the monitor and relinquish control of the object to the next waiting thread, the owner of the monitor simply returns from the synchronized method.
To understand the need for synchronization, let’s begin with a simple example that does not use it-but should. The following program has three simple classes. The first one, Callme, has a-single method named call(). The call() method takes a String parameter called msg. This method tries to print the msg string inside of square brackets. The interesting thing to notice is that after callt ) prints the opening bracket and the msg string, it call? Thread.sleep(lOOO), which pauses the current thread for one second.
The constructor of the next class, Caller, takes a reference to an instance of the Callme class and a String/which arc stored in target and msg, respectively. The constructor also creates a new thread that will call this object’s run() method. The thread is started immediately. The runt ) method of Caller calls the callt ) method on the target instance of Call me, passing in the msg string. Finally, the Synch class starts by creating a single instance of Callme, and three instances of Caller, each, with a unique message string. The same instance of Callme is passed to each Caller.
Here is the output produced by this program:
Hello [Synchronized [World]
As you can see calling sleept ), the callt ) method allows execution to switch to another thread. This results in themixed-up output of the three messagestrings.In this program, nothing.exists to stop alr1hree threads from calling the same method, on the same object, at the same time. This is known as a race condition, because the-three threads are racing each other t6″coinplete the method. -This example used’ sleept )’to make, the effe~ts .repeatable and obvious. In most situations, a race’ condition is more subtle and less predictable, because you can’t be sure when the context switch will occur. This can cause a program to run right one time and wrong the next. To fix the preceding program, you must serialize access to cal1( ). That is, you must restrict its access to-only one thread at a time. To do this, you simply need to precede calli )’s.definition with the keyword synchronized, as shown here: class Call me
synchronized void call (String msg)
This prevents other threads from entering call() while another thread is using it. After synchronized. has been added to calll }, the output of the pr09ram is as follows:
Any time that you have a method, or group of methods, that manipulates the internal state of an object in a multithreaded situation, you should use the ‘synchronized keyword to guard the state from race conditions. Remember, once a thread enters any synchronized method on an instance, no other thread can enter any other synchronized method on the same instance. However, non synchronized methods on that instance will continue to be callable.