Почему Java синхронизированные потоки печатаются из заказа? - PullRequest
0 голосов
/ 15 февраля 2020

Я запускаю этот java пример потока:

public class Locks1 extends Thread {
    private Object lock;
    private int myId;
    public Locks1( Object l, int id ) { 
      lock = l; myId = id; 
    }
    public void run() { 
      synchronized( lock ) {
        for ( int i = 0; i < 3; i++ ) {
          System.out.println( "Thread #" + myId + " is tired" ); 
        try {
          Thread.currentThread().sleep( 10 );
        } catch ( InterruptedException e ){

        } System.out.println("Thread #" + myId + " is rested" );
      }
    }
  }
    public static void main( String args[] ) {
        Integer lock = new Integer( 0 );
        for ( int i = 0; i < 4; i++ ) {
          new Locks1( lock, i ).start(); 
        }
    }
}

И у меня такой результат:

Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested

Я не понимаю, почему он печатается в таком порядке. Может кто-нибудь, пожалуйста, помогите мне понять, почему последовательность 0321 вместо 0123?

Спасибо

Ответы [ 2 ]

2 голосов
/ 15 февраля 2020

В вашем коде первая проблема заключается в том, что ресурс блокировки должен быть конечным объектом, поэтому объявите его следующим образом:

final Integer lock = new Integer( 0 );

Поскольку без этой семантики разные потоки могут блокироваться для другого объекта, однако работая на том же объекте.

И объяснение поведению, которое вы наблюдали.

Хотя целью может быть повышение общей производительности, использование нескольких потоков всегда приводит к некоторым затратам производительности по сравнению с однопоточным подходом. К ним относятся издержки, связанные с координацией между потоками (блокировка, сигнализация, синхронизация), повышенное переключение контекста, создание и удаление потоков и накладные расходы по планированию. ref.ch-11.1

Как уже говорилось, блокировка, переключение контекста и сигнализация связаны с многопоточностью по сравнению с однопоточными программами. В вашем случае причина, по которой вы получаете последовательность «0321», не воспроизводится, например, на другом компьютере.

Метод Thread.start() вызывает системный собственный метод start0, и система выделяет ресурсы, и если поток блокирует любые ресурсы (что он делает). Поскольку вашему методу требуется время (хотя и небольшое), чтобы завершить метод run(), другие потоки ожидают

Простая разница, изменяющая ваш код на этот, приведет к другому выводу. Поскольку это вводит различия во времени и планировании того, какой поток процессор возобновляет и получает следующую блокировку на Integer lock. Короче говоря, это не воспроизводимый вывод, и он будет отличаться в 1001 попытка «может быть».

 final Integer lock = new Integer( 0 );
 for ( int i = 0; i < 4; i++ ) {
    System.out.println("starting : " + i);
    new Locks1( lock, i ).start();
 }

выходы:

starting : 0
starting : 1
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
starting : 2
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
starting : 3
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested

ПРИМЕЧАНИЕ. Это опять может не воспроизводиться в вашей машине.

0 голосов
/ 15 февраля 2020

Когда несколько потоков ожидают получения блокировки и, наконец, она становится доступной, нет никакой гарантии, какой поток будет выбран. Это может быть любой. Если вы выполните тест несколько раз, вы можете получить разные результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...