Describe how access to shared objects is synchronized among multiple threads.
Synchronizing Shared Java Objects
Live in the present, enjoy the moment.
Since objects are often shared among multiple threads, it is important that access to these objects be coordinated. Otherwise, you could run into situations where one thread is updating an object while another thread is trying to use it. The coordination of thread access to shared objects is referred to as synchronization. Synchronization applies to classes as well as objects.
Synchronization Concepts
The arrowed lines in the diagram describe the thread paths between the objects.
As this diagram demonstrates, without synchronization[1] one thread may try to read an object while it is in the process of being updated. This usually results in bad data being supplied to the reader of the data(data corruption).
Java support
Java has provided support for thread synchronization since its initial release.
Java supports synchronization through synchronized methods and synchronized statements.
A synchronized method is declared by putting the synchronized keyword in the method's declaration.
For example, the following declares myMethod() as being synchronized:
public synchronized void myMethod() {
. . .
}
One synchronized Method per Object
Only one synchronized method can be invoked for an object at a given point in time. This method must return before any other synchronized methods can be invoked for that object.
Synchronization is maintained through the use of locks (also referred to as monitors[2] ).
Synchronization to remove Conflicts between competing Threads
The following program shows how to use synchronization to remove conflicts between competing threads. This program fixes the problem by adding the synchronized keyword to the update() method of MyObject. When you compile and run the program, it will display either a sequence of 20 A's followed by 20 B's or 20 B's followed by 20 A's. Synchronization ensures that one thread cannot execute update() until the other has finished.
Synchronized threads
class MyThread extends Thread {
public static void main(String args[]) {
MyThread threadA = new MyThread("A");
MyThread threadB = new MyThread("B");
threadA.start();
threadB.start();
while(threadA.isAlive() || threadB.isAlive()) {
yield();
}
MyObject.displayResult();
}
public MyThread(String id) {
super(id);
}
public void run() {
MyObject.update(getName());
}
}
class MyObject {
static String result = "";
public static synchronized void update(String name) {
for(int i=0;i<20;++i) result += name;
}
public static void displayResult() {
System.out.println(result);
}
}
Every object and class is associated with a unique lock[3]. When thread A invokes a synchronized method of an object or class, it must wait for the lock associated of that object or class.
If another thread, thread B, has acquired the lock, then thread A enters the waiting state until the lock becomes available.
Thread A invokes a synchronized method of the object.>
Because there is a lock on the object held by thread B, thread A enters the waiting state until thread B relinquishes the object's lock.
Thread B completes. It is processing and releases the object's lock. This causes threadA to enter the ready state.
Thread A is scheduled and enters the running state.
Thread Invokes Synchronized Method
A synchronized statement is similar to a synchronized method except that it applies to a single statement block instead of an entire method. Synchronized statements are declared using the following syntax:
synchronized (object) {
statement(s)
}
A thread must acquire the lock of the object before executing the synchronized statement. It relinquishes the lock once the synchronized statement has completed.