Я прав в своем предположении о синхронизированном блоке? - PullRequest
1 голос
/ 03 мая 2010

У меня есть метод shout () с синхронизированным блоком.

  private void shout(){
    System.out.println("SHOUT " + Thread.currentThread().getName());
    synchronized(this){
      System.out.println("Synchronized Shout"  + Thread.currentThread().getName());
      try {
        Thread.sleep(50);
      }
      catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("Synchronized Shout"  + Thread.currentThread().getName());
     }
  }

Если у меня есть два потока, которые запускают этот метод, правильно ли я полагаю, что два «Синхронизированных крика» всегда будут появляться один за другим? Между «Синхронизированным криком» не может быть других операторов?

Ответы [ 3 ]

2 голосов
/ 03 мая 2010

Поскольку строка, которая печатает «SHOUT ...», не требует блокировки, она может появиться в любой точке. Таким образом, даже если один поток удерживает блокировку, другой поток может войти и вывести «SHOUT ...».

Следующий код показывает чередование:

public class Interleave {
  public static void main(String[] args) throws Throwable {
    Task task = new Task();
    Thread t1 = new Thread(task);
    Thread t2 = new Thread(task);
    t1.start();
    Thread.sleep(25);
    t2.start();
  }

  private static class Task implements Runnable {
    public void run() {
      shout();
    }

    private void shout() {
      System.out.println("SHOUT " + Thread.currentThread().getName());
      synchronized (this) {
        System.out.println("Synchronized Shout "  + Thread.currentThread().getName());
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("Synchronized Shout "  + Thread.currentThread().getName());
      }
    }
  }
}

Распечатывает

SHOUT Thread-0
Synchronized Shout Thread-0
SHOUT Thread-1
Synchronized Shout Thread-0
Synchronized Shout Thread-1
Synchronized Shout Thread-1
2 голосов
/ 03 мая 2010

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

Обратите внимание, что если вы будете использовать Object.wait на this вместо вызова Thread.sleep для задержки, то блокировка будет снята (и снова получена перед продолжением).

0 голосов
/ 04 мая 2010

Когда два или более потоков работают с одним и тем же экземпляром, тогда SHOUT может появиться где угодно, потому что он находится вне синхронизированного блока и поэтому не защищен. «Синхронизированные крики» всегда будут отображаться строго по порядку, без синхронизированного крика из другого потока, который встанет между ними и повлияет на порядок.

...