Lets suppose we have many threads operating simultaneously on an instance which increments a counter by 1
But we don't want 2 or more to operate at the same time
Because this will create inconsistencies on our controlled adding - counter may increase faster and lose a value.
So, only one thread should have access to read and write at each moment.
The next thread should get the last value and increment/write on it.
And so on.
THREADS AND MAIN MEMORY
Class/Instance for incrementing counter
public class SynchronizationWithSynchronizedKeyword {
private int counter;
int getValue() {
return counter;
}
synchronized void incrementBy1() {
counter++;
}
}
@Test
public void test1() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(3);
SynchronizationWithSynchronizedKeyword syncWithKeyword = new SynchronizationWithSynchronizedKeyword();
IntStream.range(0, 1000).forEach(count -> service.execute(syncWithKeyword::incrementBy1));
shutdownAndAwaitTermination(service);
assertEquals(1000, syncWithKeyword.getValue());
}
private void shutdownAndAwaitTermination(ExecutorService pool) {
// Disable new tasks from being submitted
pool.shutdown();
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS)) {
// Cancel currently executing tasks forcefully
pool.shutdownNow();
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ex) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
public class SynchronizationWithAtomicClasses {
private final AtomicInteger counter = new AtomicInteger(0);
int getValue() {
return counter.get();
}
void incrementBy1() {
counter.incrementAndGet();
}
}
@Test
public void test2() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(3);
SynchronizationWithAtomicClasses syncWithAtomic = new SynchronizationWithAtomicClasses();
IntStream.range(0, 1000).forEach(count -> service.execute(syncWithAtomic::incrementBy1));
shutdownAndAwaitTermination(service);
assertEquals(1000, syncWithAtomic.getValue());
}