The problem is that 2 or 3, or 10 threads (it does not matter), alternately (each thread alternately after one second), decrement the variable. At first, I simply wrote a method and synchronized it, then I synchronized the object, now I do everything directly in the run method, but still all threads work in a pack, and only after performing one iteration, back again, they all fall asleep in a pack. How to consistently divide the work? Why does not synchronization help?

package nhg; import java.net.UnknownHostException; public class qq { public static void main ( String [] args ) throws UnknownHostException, InterruptedException { for (int i = 0; i < 2; i++) { new The().start(); } } public static class The extends Thread { private volatile static int q = 10; private final Object lock; The(){ lock = new Object(); } @Override public void run() { synchronized (lock) { for (q = 10; q > 0; q--) { try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("qqq"); } System.out.println(currentThread().getName() + " lift vniz " + q); } Thread.yield(); } } } } 

    2 answers 2

    The problem is this: each thread locks under its lock , respectively, you need to make lock static object of class The thus synchronization should work. Although synchronization is not a valid option here: while the thread sleeps another thread cannot enter the method, to solve this problem, transfer the synchronization purely to decreasing the variable:

     public void run() { while(q > 0){ try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("qqq"); } synchronized(lock) { q--; } System.out.println(currentThread().getName() + " lift vniz " + q); } Thread.yield(); } } 

    However, in this case, the variable can go into the negative, since I consider it two threads in parallel, you can bypass it by a separate method:

     public static synchronized boolean decr() { if(q > 0) { q--; return true; } return false; } public void run() { while(decr()) { System.out.println(currentThread().getName() + " lift vniz " + q); Thread.sleep(1000); } Thread.yield(); } 
    • So I decided, the problem was in statics) anyway, thank you very much) - alex safsafsd
     public class Main { public static void main(String[] args) throws UnknownHostException, InterruptedException { for (int i = 0; i < 2; i++) { new The().start(); } } public static class The extends Thread { private volatile static int q = 10; public static synchronized void incrementCount() { q--; } private final Object lock; The() { lock = new Object(); } void print() { for (q = 10; q > 0; incrementCount()) { try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("qqq"); } System.out.println(currentThread().getName() + " lift vniz " + q); } } @Override public void run() { print(); Thread.yield(); } } } 

    conclusion

     Thread-0 lift vniz 10 Thread-1 lift vniz 9 Thread-0 lift vniz 8 Thread-1 lift vniz 7 Thread-0 lift vniz 6 Thread-1 lift vniz 5 Thread-0 lift vniz 4 Thread-1 lift vniz 3 Thread-0 lift vniz 2 Thread-1 lift vniz 1 Thread-0 lift vniz 0 
    • I need every once in one second any trade to reduce q and bring it to the screen ... it is important that the trade was not one - alex safsafsd
    • @alexsafsafsd and what is the result? did not quite understand what you want - Senior Pomidor
    • I want to make an ordinary counter, so that any trade once per second decreases the value of q and this is displayed. The goal is to understand why my option does not work, why threads work in groups, run together and fall asleep, and find out why object synchronization does not work. And also to understand how to divide the work of tradov in this example. - alex safsafsd