Pinkk Wormm
Pinkk Wormm

Reputation: 46

Thread safe compare method

I'm trying to create a thread safe counter but I'm not sure how to thread safe compare. Is the threadCount.get() followed by '==' operator thread safe ?

public class ThreadSafeCounter {

    private final AtomicInteger threadCount = new AtomicInteger(0);

    //thread safe
    public void increment() {
        threadCount.getAndIncrement();
    }
    //thread safe
    public void decrement() {
        threadCount.getAndDecrement();
    }
    // is it safe ?
    public boolean compareWith(int integer){
        return threadCount.get() == integer;
    }

}

Upvotes: 1

Views: 430

Answers (2)

Yury Nevinitsin
Yury Nevinitsin

Reputation: 158

It is threadsafe. But it does not guarantee comparsion to be correct, because of race conditions. If we rewrite the code like this, it will be easier to see it.

    public boolean compareWith(int integer) {
        int n = threadCount.get();
        // so here, at this point, other thread(s), one, two, ten of them
        // can call increment() or decrement()
        // and so the number n which is used in the following comparsion
        // is no longer the number actually stored in threadCount
        return n == integer;
    }

Upvotes: 1

Andy Turner
Andy Turner

Reputation: 140319

The question you need to ask yourself when asking about thread safety is: what do I mean by "thread-safe"?

In fact, the question you really need to address is whether the code calling it does so safely.

You can do things with thread-safe data structures that are individually thread-safe, but are not thread safe when taken together.

Using AtomicInteger directly:

anAtomicInteger.incrementAndGet();
if (anAtomicInteger.get() < 5) {
  // ...
}

The two operations here - incrementing and getting - are both thread safe; but - according to one definition of thread safety - they're not safe when taken together, because there is a possibility that some other thread has snuck in and incremented anAtomicInteger in between the two calls.

A solution to this is to use the return value of incrementAndGet():

if (anAtomicInteger.incrementAndGet() < 5) {
  // ...
}

which is guaranteed to happen atomically, so there is no thread interference there.

The answer to your question - and the solution - depends on what problem you are trying to solve.

Upvotes: 5

Related Questions