Unsafe decrement / increase flow - why is it mostly positive?

I'm interested in learning about unsafe decrementing / incrementing in java threads, so there is my program:

Main class:

public class Start { public static void main(String[] args) { int count = 10000000, pos = 0, neg = 0, zero = 0; for (int x=0; x<10000; x++) { Magic.counter = 0; Thread dec = new Thread(new Magic(false, count)); Thread inc = new Thread(new Magic(true, count)); dec.start(); inc.start(); try { inc.join(); dec.join(); } catch (InterruptedException e) { System.out.println("Error"); } if (Magic.counter == 0) zero++; else if (Magic.counter > 0) pos++; else neg++; } System.out.println(Integer.toString(neg) + "\t\t\t" + Integer.toString(pos) + "\t\t\t" + Integer.toString(zero)); } } 

Thread Class:

 public class Magic implements Runnable { public static int counter = 0; private boolean inc; private int countTo; public Magic(boolean inc, int countTo) { this.inc = inc; this.countTo = countTo; } @Override public void run() { for (int i=0;i<this.countTo;i++) { if (this.inc) Magic.counter++; else Magic.counter--; } } } 

I ran the program several times and always got a much more positive result than a negative one. I also tried changing the thread start order, but that didn't change anything. Some results:

 Number of results < 0 | Number of results > 0 | Number of results = 0 1103 8893 4 3159 6838 3 2639 7359 2 3240 6755 5 3264 6728 8 2883 7112 5 2973 7021 6 3123 6873 4 2882 7113 5 3098 6896 6 
+6
source share
2 answers

I bet you will see the exact opposite behavior with the following change (i.e. cancel the branches without changing anything else):

 if (this.inc) Magic.counter--; // note change, and lie about `this.inc` else Magic.counter++; 

If true, what does this mean, does this indicate thread interaction?

Now, for fun, do Magic.counter volatile - [how] change the results?

How about removing volatile and the if/else environment with lock ? (A lock provides full memory access and sets a critical region. It should always give excellent results.)

Happy coding.


What to consider:

  • The code looks only from zero or more to zero, and not a general drift / change: +1 or -1 is all it takes to knock over the scales. (It might be more useful to expand the collected data.)
  • It takes a little longer to execute the else branch, since a transition is required; this is usually not a problem, but more than 10 million cycles ... one or two are not many.
  • The lack of volatility / memory Magic.counter leaves a significant contribution to the visibility of the Magic.counter variable. (I believe that the corresponding JVM can give much worse results ...)
  • The ++ and -- operators -- inherently non-atomic.
  • Alternation of alternation is usually โ€œnon-deterministicโ€; less if executed across multiple cores.
+6
source

Generally speaking, this is related to how the Java memory model works. You get access to shared variables in two separate threads without synchronization. Also, the variable is declared unstable, and you are not performing atomic operations. The absence of coordination and atomic or mutable variables will lead to internal optimization of the code flow executed by the JVM when executed. In addition, non-volatile variables that did not cross the memory barrier (i.e., synchronized ) will lead to cached values โ€‹โ€‹per stream - and, therefore, conflicting local streams will result in two caches.

Given the lack of a consistent Java consistency model, complex runtime optimizations, and the features of the JVM and the underlying system (single or multi-core hyperthreading), it is impossible to predict the result deterministically - just because it violates several multi-threaded conventions for the Java language model. Executing the same code on the same computer can lead to similar results, but due to the effects of thread scheduling, CPU usage of other OS processes, etc. They are unlikely to be exactly the same.

Here are some resources about JMM: http://www.cs.umd.edu/~pugh/java/memoryModel/

0
source

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


All Articles