Java synchronized Modifier/Block - Exclusive Control in a Multithreaded Environment
synchronized
When manipulating shared data in a multithreaded environment, you must be careful about processing conflicts. The synchronized modifier is used for exclusive control in a multithreaded environment.
When synchronized Is Not Used
The following task increments the instance variable count simultaneously from multiple threads.
package com.devkuma.basic.thread;
public class SynchronizedSample {
private int count;
private static int THREAD_MAX = 300000;
private static class MyThread implements Runnable {
private SynchronizedSample _count;
public MyThread(SynchronizedSample count) {
this._count = count;
}
@Override
public void run() {
_count.increment();
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedSample ss = new SynchronizedSample();
Thread[] ts = new Thread[THREAD_MAX];
for (int i = 0; i < THREAD_MAX; i++) {
ts[i] = new Thread(new MyThread(ss));
ts[i].start();
}
for (int i = 0; i < THREAD_MAX; i++) {
ts[i].join();
}
System.out.println(ss.count); // Result: 299944 (the result differs each time)
}
public void increment() {
this.count++;
}
}
The code above does not work correctly. In the this.count++ operation, another thread may interrupt after the count value is read and before it is incremented and assigned again.
Therefore, although the final result should originally be 300,000, a value such as 299999 may be returned.
synchronized Method
To prevent this, add the synchronized modifier to the increment method.
public synchronized void increment() {
this.count++;
}
By doing this, the increment method will not be called simultaneously from multiple threads. Later callers wait until the earlier processing finishes. As a result, you can get 300,000 every time.
synchronized Block
The code above can also be rewritten using a synchronized block as follows.
public void increment() {
synchronized(this) {
this.count++;
}
}