ilovetolearn
ilovetolearn

Reputation: 2060

Java Thread Safe Counter

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

Answers (4)

Laura Liparulo
Laura Liparulo

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

BlackJoker
BlackJoker

Reputation: 3191

Your Counter is not shared through the 3 threads, instead, each thread has a unique Counter

Upvotes: 9

rongenre
rongenre

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

JB Nizet
JB Nizet

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

Related Questions