Synchronized Methods and Blocks
How to use synchronised methods and blocks
Thread interference and memory consistency errors may occur when threads share access to common objects. Multiple threads may access the same data or fields at the same time. A thread's sequence of operations on the data may overlap with those of another thread; each thread may have a different view of the values in the variables because it assumes that no other thread is working on the data. Synchronized methods prevent these problems; only one thread may access a synchronized method at any point of time. In other words, synchronized methods are 'thread safe' - they cannot be concurrently accessed.
The following class simply doubles or halves its single integer field that is initially set to 2.
public class DoubleHalve {
private int i=2;
public void doubleThis() {
i = i* 2;
}
public void halveThis() {
i /= 2;
}
public int getValue() {
return i;
}
Now, look at the following sequence of events:
- Threads A and B access the same instance of the DoubleHalve object at the same time.
- Thread A doubles its value to 4.
- Thread B halves its value to 1.
- A call to getValue shows 1.
The result of thread A (i halved to 2) is lost. This is just one scenario; Thread B may get to the object first or the results may even be correct. Uncertain results and inconsistent views may be avoided by using synchronized methods in the DoubleHalve class:
public class DoubleHalve {
private int i=2;
public synchronized void doubleThis() {
i = i* 2;
}
public synchronized void halveThis() {
i /= 2;
}
public synchronized int getValue() {
return i;
}
When a thread is executing a synchronized method, other threads 'block' or suspend execution until the current thread is done. Also, synchronized methods work in such a way that two threads cannot retrieve values of objects and variables within the method at the same instant; the threads access the objects in strict sequence.
When many threads should be prevented from accessing just a few lines of code rather an entire method, blocks of code may also be synchronized. However, the object that requires a lock should be specified (the current instance is locked in the following example):
synchronized (this) {
x = (a*b*c)/d;
.
.
(Thread Safe Code)
.
.
}
All objects possess intrinsic locks. Synchronized methods and loops work by acquiring the lock and 'owning' it while accessing the object. Once the method ends (even if the termination is abnormal) the lock is released. A thread executing a synchronized static method acquires a lock for the entire class (static methods are class methods)