1

Studying the atomic classes i found this code :

public class AtomicCounter {

private AtomicLong count = new AtomicLong(0);

public void increment() {
    boolean updated = false;
    while(!updated){
        long prevCount = count.get();
        updated = count.compareAndSet(prevCount, prevCount + 1);
    }
}

public long count() {
    return count.get();
}

And i asked myself what if the following scenario occurs :

  1. In thread A the boolean updated is changed to true after calling the method compareAndSet.

  2. In thread B the instruction boolean updated = false; is executed and the boolean updated is changed again to be false

  3. In thread A the loop while check the value of the boolean updated which recently changed to false so another leap will be take a place.

In this case the thread A will take a new leap in while even it has already change the value of updated to true because in the time between of this change and the checking of updated by while the other thread B has changed the value of updated to false. How far this scenario is true ?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    I formatted your numbering. Stack Overflow does support basic HTML through their flavor of Markdown. I do recommend you take advantage of that where useful. – Basil Bourque Sep 30 '22 at 22:19
  • 1
    Threads share `AtomicCounter` and so they would also share it's `count` variable. `updated` being local means it only exists in the context of the current execution of the method. Even recursively calling the method in the same thread would have a new local version each time. And if you recurse too deep you get a stackoverflow because there are too many of them to fit in memory (or the stack to be precise). – zapl Sep 30 '22 at 22:37

1 Answers1

2

Local variable not shared between threads

You misunderstand how local variables work with threads.

Each thread has its own local variables.

Local variables are kept on the call stack. Each thread has its own call stack. So in your scenario, two updated vars exist.

See the Question, Why are local variables thread safe in Java.

So your threads A and B each have their own updated variable. One thread changing the value updated has no effect on the other thread’s updated variable.

How far this scenario is true ?

Step # 1 is correct.

Steps 2 & 3 are incorrect.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • If A and B each have their own updated variable so i assume when we call `System.identityHashCode(updated)` we will get different ID umbers but it's not the case ( at least for my test ). Why ? – taher bouali Sep 30 '22 at 22:35
  • 2
    @taherbouali Variables don't have an identity. You're just boxing the variable to a constant reference via `Boolean.valueOf()`. – shmosel Sep 30 '22 at 22:38
  • @taherbouali `boolean updated` is not an object. It is a primitive. The `System.identityHashCode` method takes an object reference, not a primitive. – Basil Bourque Sep 30 '22 at 22:38
  • @shmosel Interesting explanation. I was wondering how passing a primitive to that method would pass the compiler. Thank you. – Basil Bourque Sep 30 '22 at 22:40
  • @taherbouali See [tutorial on boxing](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) by Oracle. – Basil Bourque Sep 30 '22 at 22:42
  • @shmosel So threre is no way to identify an object in Java ? – taher bouali Sep 30 '22 at 22:47
  • `updated` is not an object, as @BasilBourque explained. – shmosel Sep 30 '22 at 22:50
  • @Basil Bourque I know that `boolean updated` is a primitive and not an object but believe it or not i passed it to the method `System.identityHashCode` and it worked without problems ( Im using Java 8 on Intellij IDEA ). May be it accept the primitive and it convert it internally to a wrapper object. – taher bouali Sep 30 '22 at 22:51
  • 1
    @taherbouali As [shmosel commented](https://stackoverflow.com/questions/73914398/how-to-manage-the-concurrent-access-in-atomiclong-class/73914476?noredirect=1#comment130511496_73914476) the likely explanation is that the primitive `boolean` value you passed to `System.identityHashCode` was auto-boxed, likely into the constant [`Boolean.TRUE`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html#TRUE) or `Boolean.FALSE` object. So two references to the same constant `Boolean` object will show same identity. This is unrelated to your two `updated` vars existing. – Basil Bourque Sep 30 '22 at 23:18
  • @taherbouali See two primitive `boolean` local vars returning same hash in this [code running at Ideone.com](https://ideone.com/FXMRCe). – Basil Bourque Sep 30 '22 at 23:29