1

I'm trying to understand what is the possible value of classMember that two threads are updates, When I'm running the program the output is always 20, But I want to understand why its happend and what is the mimumum, maximum value of classMember

public class TestClass {


public int classMember = 0;
    private void updateCM() {
        for (int i = 0; i < 10; i++) {
            classMember++;
        }
    }
public static void main(String[] args) {

    TestClass mainClass = new TestClass();
    Thread t1 = new Thread(mainClass::updateCM);
    Thread t2 = new Thread(mainClass::updateCM);

    t1.start();
    t2.start();

    while(t1.isAlive() || t2.isAlive()) {}

    System.out.println(mainClass.classMember);
}

}
Yaakov
  • 53
  • 5

6 Answers6

3

I think you need to read this Stackoverflow thread

Make multiple threads use and change the same variable

Since you are updating the same variable in the same instance you may have synchronization issues. The appropriate keyword for this case would be volatile. But even if you set volatile to your variable this will not be enough because the ++ is actualy not a single but three operations which makes it non atomic.

I will quote this passage also

Although this takes care of memory synchronization, it doesn't necessarily protect you from race conditions. It is also important to realize that ++ is actually 3 operations: get the current value, increment it, and store it back again. If multiple threads are trying to do this, there are thread race-conditions which can cause the ++ operations to be missed. In this case, you should use the AtomicInteger class which wraps a volatile int field. It gives you methods like incrementAndGet() which do the job of incrementing that field in a thread-safe manner.

Alexander Petrov
  • 9,204
  • 31
  • 70
  • 1
    The `++` operation being non-atomic is actually a really important point. With longer interations you would likely see inconsistent results. – Mick Mnemonic Mar 02 '18 at 12:05
  • 1
    `volatile` sill doesn't solve the non-atomicity of the increment operation. https://stackoverflow.com/questions/7805192/is-a-volatile-int-in-java-thread-safe – Mark Jeronimus Mar 02 '18 at 12:37
  • @MarkJeronimus thanks. I see that It how the voliatize is related to the ++ operation is not well specified in the text. I edited it. – Alexander Petrov Mar 02 '18 at 12:41
1

Increment is not atomic operation, so results can be different each time you run the program. In this case, I think, first thread just completes incrementing variable's value before processor gives the second thread a time to perform it's operations. But if you, for example, start two threads, where first will decrement the variable's value a billion of times, and the second thread is the opposite - incrementing it a billion of times, you will get something pretty unexpected (sure, if you are not going to make this variable thread-safe).

nyarian
  • 4,085
  • 1
  • 19
  • 51
1

All values between 10 and 20 (inclusive) are possible outcomes.

In the worst case scenario, every increment (which is not atomic and consists of Read-memory, increase, write-memory) of one thread is interleaved with other threads.

Possible interleaving (the 'increase' operation omitted for bevity):

Thread1  Thread2
Read 0
         Read 0
Write 1
         Write 1
Read 1
         Read 1
Write 2
         Write 2
Read 2
         Read 2
Write 3
         Write 3
Read 3
         Read 3
Write 4
         Write 4
Read 4
         Read 4
Write 5
Read 5
         Write 5
         Read 5
Write 6
Read 6
         Write 6
         Read 6
Write 7
Read 7
         Write 7
         Read 7
Write 8
Read 8
         Write 8
         Read 8
Write 9
Read 9
         Write 9
         Read 9
         Write 10
Write 10

Another possible interleaving:

Thread1  Thread2
Read 0
         Read 0
         Write 1
         Read 1
         Write 2
         Read 2
         Write 3
         Read 3
         Write 4
         Read 4
         Write 5
         Read 5
         Write 6
         Read 6
         Write 7
         Read 7
         Write 8
         Read 8
         Write 9
         Read 9
         Write 10
Write 1
Read 1
Write 2
Read 2
Write 3
Read 3
Write 4
Read 4
Write 5
Read 5
Write 6
Read 6
Write 7
Read 7
Write 8
Read 8
Write 9
Read 9
Write 10
Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
  • The question is about the minimum and maximum values of the variable. Not about the possible outcomes. – Andres Mar 03 '18 at 10:24
0

The minimum is the initialization value, that is 0.

Concerning the maximum, though you create two instances of Thread, both instances use the same instance of TestClass, therefore, incrementing the classMember variable 2 times * 10 times, you get a value of 20.

Andres
  • 10,561
  • 4
  • 45
  • 63
0

Most probably due to 'luck', or 'too small sample' if you will. The JIT compiler will not have yet done its work, so whatever is run may not be optimal and use simple techniques.

If you change your maximum from 10 to 1,000,000 you will see that the total does indeed not add up and will yield different results at different runs.

M. le Rutte
  • 3,525
  • 3
  • 18
  • 31
-2
TestClass mainClass = new TestClass(); 

Now the value is set to 0.

t1.start(); // 0-10
t2.start(); /10- 20

In the end, classMember is 20.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
Praveen PL
  • 41
  • 1
  • 2