You need to create a class containing a static variable with the public modifier. Then start from main 2 different threads, which will randomly change this global variable until they finish. I did this:

public class MyThread extends Thread { public synchronized void Change(int a) { if (a % 2 == 0) MainClass.variable +=2; else MainClass.variable -=2; } public void run() { for(int i=0;i<10;i++) { Change(i); System.out.println("V = "+MainClass.variable+"\ti = "+i+"\t Thread Name "+this.getName()); } } } 


 public class MainClass { public static volatile int variable = 0; synchronized protected void CreateThread() { Thread task = new MyThread(); task.start(); } public static void main(String args[]) { MainClass mc=new MainClass(); mc.CreateThread(); mc.CreateThread(); } } 

But it works incorrectly. It is necessary that all changes to the variable be visible on the screen, that is, if one of the threads has increased or decreased the MainClass.variable, it must display it on the screen before control passes to another stream. Otherwise, it turns out nonsense, the console displays a completely unpredictable value of MainClass.variable. What did I do wrong?

    4 answers 4

    You need to make the MainClass.variable private and access it via secure ( synchronized ) getters and setters. Otherwise, everything will fall out.

    It is ideologically wrong to try to synchronize access to a global public variable. Anyway, there will be some kind of scum who will directly knock on a variable and then yell that it works!

    Update Having read again in the post of the author, I noted what I had previously missed:

    he must display it before the control passes to another thread

    IMHO it just means that you need to synchronize the output of data together with the setter, then it will be correctly displayed and changed.

    • Agree with @Next_Alex getter's announcement synchronized is brute force - Barmaley
    • The council, as it is considered necessary to program, is nice, but it does not at all explain the output on the screen observed by the author. - avp

    Thought worked in the right direction, but not to the end. The point is that any access to a variable must be thread-safe, and you have the value of a variable changed in a protected method, and then you get this value by directly accessing the variable, although at this point the second thread just changes it.

    The easiest way is that the Change method should return a new value of the variable, or the output of the value should occur inside the Change method.

    • one
      Synchronization through protected setters is, of course, very correct, but only protects against attempts to simultaneously change the value of a variable. There is no point in defending getters. Specifically, in the above case, the problem lies in the fact that the variable is changed in the flow-protected method, and the output value is after the exit from this protected method and the release of all locks. Accordingly, at the moment of obtaining the value, it may well be changed or already be changed by the second stream. And a protected getter will not help here. - Next_Alex
    • one
      All that is needed is to make the change and getting the new value of a variable in one closed zone. - Next_Alex

    The most correct is to designate a variable as volatile And there is nothing more.

    see an example , ttst very clearly all shown and you can modify it for yourself

    • @Gorets it is already designated as volatile - Barmaley
    • I see, this should be enough, without synchronization blocks - Gorets
    • I changed the code: ... private volatile static int variable = 0; synchronized public static void SetVariable (int k) {variable = k; } synchronized public static int GetVariable () {return variable; } ... and ... private synchronized void Change (int a) {int k = MainClass.GetVariable (); if (a% 2 == 0) k + = 2; else k - = 2; System.out.println ("V =" + k + "\ ti =" + a + "\ t Thread Name" + this.getName ()); MainClass.SetVariable (k); } But now each thread makes a copy of a variable, but it’s necessary that if 1 thread adds 2, and then it earns 2, then 2 also adds and leaves 4. And 2 2 0 0 2 2 is output - galileopro
    • That is, the first stream outputs 2, then the second stream receives control and outputs 02 (although the first stream has already increased the value by 2 and should be 4), etc. I also noticed that how many times do not start this program, the system transfers control alternately flows, although earlier they could be executed in an arbitrary order. It is not necessary for me to alternately change the variable, in any order, but how to make it so that if 1 thread adds a two, then the second adds 2 to the new value, and not to zero? It seems to be a private variable, the output occurs in the same method as the changes. - galileopro
    • By the way how to make out the correct code? I don’t see buttons for inserting a block of code in the answer field (The purpose of this work is for the threads to change the variable variable in an arbitrary order, but if one thread changed, then the second thread already changed the changed value (tautology, but understandable). Therefore, I did the public. Plus, immediately after the change, the new value was displayed on the screen, and there was no such thing that while it was being displayed on the screen, some stream changed it again and it was unclear what. Or did not have time to change, but it was already displayed on the screen. : changed the variable, deduced, transferred control. - galileopro

    Create a synchronized setter for this variable, like so

     private static Integer param; public static synchronized void setParam(Integer value){ param=value; }