Reputation: 2060
I am learning to write thread-safe programs and how to evaluate codes which are not thread safe.
A class is considered thread-safe if it function correctly when executed by multiple threads.
My Counter.java is not a thread-safe one, however the output was printed as expected from 0-9 for all 3 threads.
Can anyone explains why? and how thread-safety works?
public class Counter {
private int count = 0;
public void increment() {
count++;
}
public void decrement() {
count--;
}
public void print() {
System.out.println(count);
}
}
public class CountThread extends Thread {
private Counter counter = new Counter();
public CountThread(String name) {
super(name);
}
public void run() {
for (int i=0; i<10; i++) {
System.out.print("Thread " + getName() + " ");
counter.print();
counter.increment();
}
}
}
public class CounterMain {
public static void main(String[] args) {
CountThread threadOne = new CountThread("1");
CountThread threadTwo = new CountThread("2");
CountThread threadThree = new CountThread("3");
threadOne.start();
threadTwo.start();
threadThree.start();
}
}
Upvotes: 0
Views: 10224
Reputation: 2897
Try with this:
public class ThreadSafeCounter {
AtomicInteger value = new AtomicInteger(0);
public ThreadSafeCounter(AtomicInteger value) {
this.value = value;
}
public void increment() {
value.incrementAndGet();
}
public void decrement() {
value.decrementAndGet();
}
public AtomicInteger getValue() {
return value;
}
}
Upvotes: 2
Reputation: 3191
Your Counter
is not shared through the 3 threads, instead, each thread has a unique Counter
Upvotes: 9
Reputation: 1334
So that's actually thread-safe. For every CountThread, there's one counter. To make it not thread safe, change the counter variable to:
private static Counter counter = new Counter();
Then it wouldn't be thread safe because different threads could be modifying the counter state at the same time.
Upvotes: 2
Reputation: 691913
Your code runs fine in your specific test. That doesn't mean it will always work fine. Try iterating a lot more times, and you'll probably start seeing anomalies.
Your test is a bit like if you tested that a bridge can support 20 trucks by riding on the bridge with a single car. It doesn't demonstrate anything. And demonstrating that th code is thread-safe using a test is almost impossible. Only careful reading and understanding of all the potential problems can guarantee that. A non thread-safe program might work fine for years and suddenly have a bug.
To make you counter safe, use an AtomicInteger.
EDIT :
Also, as noted by @SpringRush, you're not sharing a single counter between threads. Each thread has its own counter. So your code is actually thread-safe, but I don't think it does what you intend it to do.
Upvotes: 5