daniel sp
daniel sp

Reputation: 1000

Why is this code thread safe?

I am preparing for the OCP exam and I found this question in a mock exam:

Given:

class Calculator {
    private AtomicInteger i = new AtomicInteger();
    public void add(int value) {
        int oldValue = i.get();
        int newValue = oldValue + value;
        System.out.print(i.compareAndSet(oldValue,newValue));
    }
    public int getValue() {
        return i.get();
    }
}

What could you do to make this class thread safe?

And surprisingly, to me, the answer is: "Class Calculator is thread-safe"

It must be that I have not understood correctly the concept. To my understanding, a class is thread safe when all the methods work as expected under thread concurrency. Now, if two thread call at the same time getValue(), then call add() passing a different value, and then they call getValue() again, the 'second' thread won't see its value passed increased.

I understand that the oldValue and the newValue as local variables are stored in the method stack, but that doesn't prevent that the second call to compareAndSet will find that the oldValue is not the current value and so won't add the newValue.

What am I missing here?

Upvotes: 4

Views: 415

Answers (4)

biziclop
biziclop

Reputation: 49714

There is clearly a problem with the term "thread-safe" here, in that it isn't absolute. What is considered thread-safe depends on what you expect the program to do. And in most real-world applications you wouldn't consider this code thread-safe.

However the JLS formally specifies a different concept:

A program is correctly synchronized if and only if all sequentially consistent executions are free of data races.

If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent

Correctly synchronized is a precisely defined, objective condition and according to that definition the code is correctly synchronized because every access to i is in a happens-before relationship with every other access, and that's enough to satisfy the criteria.

The fact that the exact order of reads/writes depends on unpredictable timing is a different problem, outside the realms of correct synchronization (but well within what most people would call thread safety).

Upvotes: 3

Stephen C
Stephen C

Reputation: 718698

The add method is going to do one of two things:

  • Add value to the value of i, and print true.
  • Do nothing and print false.

The theoretically sound1 definitions of thread-safe that I have seen say something like this:

Given a set of requirements, a program is thread-safe with respect to those requirements if it correct with respect to those requirements for all possible executions in a multi-threaded environment.

In this case, we don't have a clear statement of requirements, but if we infer that the intended behavior is as above, then that class is thread-safe with respect to the inferred requirements.

Now if the requirements were that add always added value to i, then that implementation does not meet the requirement. In that case, you could argue that the method is not thread-safe. (In a single-threaded use-case add would always work, but in a multi-threaded use-case the add method could occasionally fail to meet the requirement ... and hence would be non-thread-safe.)


1 - By contrast, the Wikipedia description (seen on 2016-01-17) is this: "A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time." The problem is that it doesn't say what "safe execution" means. Eric Lippert's 2009 blog post "What is this thing you call thread-safe" is really pertinent.

Upvotes: 2

user140547
user140547

Reputation: 8200

According to JCIP

A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.

Although there is no definition of thread-safety and no specification of the class, in my opinion, by any sane definition of an add method in a Calculator class it is "correct" if it the value of the AtomicInteger i is increased in any case, "regardless of the scheduling or interleaving of the execution".

Therefore, in my opinion, the class is not thread-safe by this definition.

Upvotes: 3

Jim W
Jim W

Reputation: 512

It's threadsafe because compareAndSet is threadsafe and that's the only part that's modifying shared resources in the object.

It doesn't make a difference how many threads enter that method body at the same time. The first one to reach the end and call compareAndSet "wins" and gets to change the value while the others find the value has changed on them and compareAndSet returns false. It never results in the system being in an indeterminate state, though callers would probably have to handle the false outcome in any realistic scenario.

Upvotes: 0

Related Questions