我对同步块的假设是否正确?

时间:2010-05-03 03:27:29

标签: java concurrency multithreading synchronized synchronized-block

我有一个带有synchronized块的方法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 个答案:

答案 0 :(得分:2)

只要this引用相同即可。如果在两个不同的对象上运行代码,则锁定将无效。

注意,如果您在Object.wait上使用this而不是调用Thread.sleep来延迟,那么锁定将被删除(并在继续之前重新获取)。

答案 1 :(得分:2)

由于打印“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 :(得分:0)

当两个或多个线程针对同一个实例运行时,SHOUT可以出现在任何地方,因为它在同步块之外,因此无人看守。 “同步喊叫”将始终严格按顺序出现,其他线程之间没有同步的喊叫,并影响订单。