Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ammadkhalid/43d52befde584228697da696d435c420 to your computer and use it in GitHub Desktop.

Select an option

Save ammadkhalid/43d52befde584228697da696d435c420 to your computer and use it in GitHub Desktop.
Java Thread Safe Concurrency

A practical deep-dive into Java concurrency, illustrating how race conditions occur during parallel non-atomic modifications and how to successfully mitigate them using internal class serialization vs. client-side explicit ReentrantLock coordination.

import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
interface incrementCounter {
void increment();
int getCounter();
}
class TestThread implements Runnable {
final private String message;
final private ThreadSafeCounter sharedValue;
final private int howManyTimes;
public TestThread(String message, ThreadSafeCounter sharedValue, int howManyTime) {
this.message = message;
this.sharedValue = sharedValue;
this.howManyTimes = howManyTime;
}
private void increment() {
for (int i = 0; i < howManyTimes; i++) {
this.sharedValue.increment();
}
}
@Override
public void run() {
try {
// lock the thread..
increment();
Thread.sleep(1000);
} catch (InterruptedException exception) {
System.err.println(exception.getMessage());
} finally {
// unlock the thread...
System.out.println("Hi! from TestThread " + message + " " + sharedValue + " " + howManyTimes);
}
}
}
class ThreadSafeCounter implements incrementCounter {
private int counter = 0;
final private Lock lock = new ReentrantLock();
@Override
public void increment() {
lock.lock();
try {
counter++;
} finally {
lock.unlock();
}
}
@Override
public int getCounter() {
lock.lock();
try {
return counter;
} finally {
lock.unlock();
}
}
}
public class thread {
public static void main(String[] args) {
ThreadSafeCounter sharedCounter = new ThreadSafeCounter();
TestThread testThreadOne = new TestThread("T1", sharedCounter, 100 * 1000);
TestThread testThreadTwo = new TestThread("T2", sharedCounter, 100 * 1000);
List<Thread> threads = List.of(new Thread(testThreadOne), new Thread(testThreadTwo));
for(Thread thread: threads) {
thread.start();
}
// wait for all of them to be finished!
threads.forEach(thread -> {
try {
thread.join();
} catch (InterruptedException exception) {}
});
// print final value
System.out.println("Final Shared Counter: " + sharedCounter.getCounter());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment