Why does changing a shared variable in one thread affect another thread even without using variability?

Here I have three simple classes:

Grade 1:

public class ThreadSyncMain { public static int count = 0; // volatile is not use public static void main(String[] args) { Thread thread1 = new Thread( new Thread1(),"Thread1" ); Thread thread2 = new Thread( new Thread2(),"Thread2"); thread1.start(); thread2.start(); } } 

Grade 2:

 public class Thread1 implements Runnable{ public void run() { System.out.println("Thread1 Count :: "+ThreadSyncMain.count); ThreadSyncMain.count++; } } 

Grade 3:

 public class Thread2 implements Runnable{ public void run() { System.out.println("Thread2 Count :: "+ThreadSyncMain.count); } } 

Output:

Thread1 Count :: 0
Thread2 Count :: 1

This means that thread1 has changed the value of count. So why does a change in thread1 affect thread2 since I am not using any kind of "mutable" keyword. Is the β€œerratic” keyword not an issue in this scenario? How can I change the code to check volatile?

Thanks in advance.

Update part: I update the code after performing trial and trial tests. Class 1 remains the same. Here is the updated code:

Class 2: I added a delay of 100 milliseconds.

 public class Thread1 implements Runnable{ public void run() { System.out.println("Thread1 Count :: "+ThreadSyncMain.count); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ThreadSyncMain.count++; } } 

Class 3: added while loop. Inside his account is constantly monitored.

 public class Thread2 implements Runnable{ public void run() { while(true) { if(ThreadSyncMain.count == 1) { System.out.println("Thread2 Count :: "+ThreadSyncMain.count); } } } } 

Now in this situation, I got the following results:
1. If "volatile" is not used to exit class 1:

  Thread1 Count :: 0 

2. If the release of class1 uses "volatile":

 Thread1 Count :: 0 Thread2 Count :: 1 Thread2 Count :: 1 Thread2 Count :: 1 . . . 

Why does volatility appear in this scenario?

+4
source share
3 answers

There is a kind of memory associated with each thread. These views do not guarantee consistency between threads without the use of locks. Thus, sharing a variable, as you did above (without volatile ), will work, since it is visible across threads, but may give you unreliable results. Using the volatile keyword means that a variable is read sequentially between threads.

See here , and in particular, note:

Flying fields are special fields that are used to communicate the state between threads. Each reading volatile will see the last record to that which is volatile by any thread; in fact, they are designated by the programmer as fields for which it is never acceptable to see the "obsolete" value as a result of caching or reordering.

+3
source

Volatile ensures that side effects from stream 1 become visible to stream 2. Without Volatile changes may or may not be visible.

Testing the Volatile effect is difficult, as it depends on aspects such as hardware architecture, thread implementation, compiler optimization, and the exact time even from the scheduler.

If I did this, I would write multi-threaded tests that generate high concurrency, and make sure that I run a multi-processor implementation. Then I could observe the differences between the code with and without Volatile . The test result will still be uncertain.

+3
source

Perhaps the compiler does not cache the counter, because it is a class variable. Thus, the entries are stored in memory.

If you want to test volatile and non-volatile records / readings ...

 public class VolatileExperiment { private int counter ; private volatile int volatile_counter; public void Counter() { new Thread( new Runnable(){ public void run() { ++counter; ++volatile_counter; //print } }).start(); new Thread( new Runnable(){ public void run() { ++counter; ++volatile_counter; //print } }).start(); //print counter //print volatile } 

}

Using volatile ensures that the compiler does not optimize the code, so writes are made to memory, not to streaming memory. So you should see volatile_counter updated .. while counter cannot be affected

+1
source

Source: https://habr.com/ru/post/1445970/


All Articles