Synchronization
Synchronization is a process of allowing only one thread at a time
Lock:
Synchronization is built around an internal entity known as the lock
or monitor. Every object has a lock associated with it. By convention, a thread
that needs consistent access to an object’s fields has to acquire the object’s
lock before accessing them, and then release the lock when it’s done with them.
Problem without Synchronization
class Counter implements Runnable {
private int count;
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
waitCounter (i);
count++;
}
}
public int getCount() {
return this.count;
}
public void waitCounter(int i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadSafety {
public static void main(String[] args) throws InterruptedException {
Counter c = new Counter();
Thread t1 = new Thread(c);
t1.start();
Thread t2 = new Thread(c);
t2.start();
// wait for threads to finish processing
t1.join();
t2.join();
System.out.println("Processing count=" + c.getCount());
}
}
-----------------------
Processing count=8
In above example for a single thread Counter we created two child threads t1,t2 and count is a variable common for those two threads. After completion of thread execution, the counter must be 10. But here it is displaying output as 8 because two threads are executing parallel on same method waitCounter(), the result may is overlapped two threads are executing same method at same time.
To resolve these types of problems we use synchronization. We can implement synchronization is 3 ways
1. Synchronized Instance Methods
2. Synchronized Static Methods.
3. Synchronized Blocks
1. Synchronized Instance methods:
If the ordinary instance method is made it as synchronized, then the object of the corresponding class will be locked
synchronized void waitCounter(int i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2. Synchronized static method
If an ordinary static method is made it as synchronized then the corresponding class will be locked.
synchronized static void waitCounter(int i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
3. Synchronized block:
When we inherit non-synchronized methods from either base class or interface into the derived class, we cannot make the inherited method as synchronized. Hence, we must use synchronized blocks
public void waitCounter(int i) {
synchronized (this) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
If you use any of above methods the output should be Processing count=10