call() and synchronized keyword - When and how to use in Java
By: Ivan Lim Printer Friendly Format
Synchronization is easy in Java, because all objects have their own implicit monitor associated with them. To enter an object's monitor, just call a method that has been modified with the synchronized keyword. While 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 call( ) prints
the opening bracket and the msg
string, it calls Thread.sleep(1000), 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 are 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 run( ) method of Caller calls the
call( ) method on the target instance of Callme, 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.
// This program is not synchronized.
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run() {
target.call(msg);
}
}
class Synch {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
Here is the output produced by this program:
Hello[Synchronized[World]
]
]
As you can see, by calling sleep( ), the call( ) method
allows execution to switch to another thread. This results in the mixed-up output of the three
message strings. In this program, nothing exists to stop all three 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 to complete the method. This
example used sleep( ) to make the effects 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 call( ). That is, you must restrict its access to only one thread at a time. To do this, you simply need to precede call( )'s definition with the keyword synchronized, as shown here:
class Callme {
synchronized void call(String msg) {
...
This prevents other threads from entering call( ) while another thread is using it. After synchronized has been added to call( ), the output of the program is as follows:
[Hello]
[Synchronized]
[World]
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.
Comment on this tutorial
- Data Science
- Android
- AJAX
- ASP.net
- C
- C++
- C#
- Cocoa
- Cloud Computing
- HTML5
- Java
- Javascript
- JSF
- JSP
- J2ME
- Java Beans
- EJB
- JDBC
- Linux
- Mac OS X
- iPhone
- MySQL
- Office 365
- Perl
- PHP
- Python
- Ruby
- VB.net
- Hibernate
- Struts
- SAP
- Trends
- Tech Reviews
- WebServices
- XML
- Certification
- Interview
categories
Subscribe to Tutorials
Related Tutorials
Program using concept of byte long short and int in java
Update contents of a file within a jar file
Tomcat and httpd configured in port 8080 and 80
Count number of vowels, consonants and digits in a String in Java
Student marks calculation program in Java
Calculate gross salary in Java
Calculate average sale of the week in Java
Vector in Java - Sample Program
MultiLevel Inheritance sample in Java
Archived Comments
1. drearmaCymn
View Tutorial By: drearmaCymn at 2012-02-03 01:35:44
2. thanks!
View Tutorial By: shgy at 2016-03-31 07:58:35