Several threads showing a value other than System.out.println are presented in the critical section.

I have the following codes:

public class MyApp {
    public static void main(String[] args) throws InterruptedException {
        SharedResource sharedResource = new SharedResource();

        Runnable first = () -> {
            sharedResource.increment(10000);
        };

        Runnable second = () -> {
            sharedResource.increment(10000);
        };

        Thread thread = new Thread(first, "FirstThread");
        Thread thread2 = new Thread(second, "SecondThread");
        thread.start();
        thread2.start();
        thread.join();
        thread2.join();
        System.out.println("The value of counter is " + sharedResource.getCounter());
    }
}

Using this class:

public class SharedResource {
    private int counter;

    public void increment(int times) {
        for (int x=1; x<=times;x++) {
            counter++;
            // System.out.println(counter);
        }
    }

    public void decrement() {
        counter--;
    }

    public int getCounter() {
        return counter;
    }
}

I am curious why this happens all the time.

When System.out.println()removed from the increment method, the total value

System.out.println("The value of counter is " + sharedResource.getCounter());

is random - this is eliminated because multiple threads use the same one counter.

However, when System.out.println(counter);presented in the increment method, the code no longer has a multithreading problem.

The end result of the counter is always 20,000, except that the code processes 10,000 times from each thread. Can someone explain to me why this is happening?

+4
1

- .

- PrintStream, :

public void println(int x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

, :

  • (~ ns)
  • , , (~ , 1000 ).
  • 1

, 1000 , , , .

:

  • PrintStream:

    public class NullPrintStream extends PrintStream {
      public NullPrintStream() {
          // Utility constant from apache-commons
          super(NullOutputStream.NULL_OUTPUT_STREAM);
      }
    
      @Override
      public void println(int x) {
         // No synchronization here
      }
    }
    

System.setOut(new NullPrintStream()), .

  1. , runnables , :

    CountDownLatch latch = new CountDownLatch(1);
    Runnable first = () -> {
      try {
        latch.await();
        sharedResource.increment(10000);
      }
      catch (Exception e) {
      }
    };
    // ... start your threads here
    latch.countDown();
    

, , - ( , System.err, System.out)

20000

- 19996

- 19994

- 19999

20000

+5

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


All Articles