使用内部锁进入块

我没有看到下面的代码如何产生看起来违反对象锁定义的输出。 当然只允许一个线程打印“获取的锁定”消息,但他们都这样做?

class InterruptThreadGroup { public static void main(String[] args) { Object lock = new Object(); MyThread mt1 = new MyThread(lock); MyThread mt2 = new MyThread(lock); mt1.setName("A"); mt1.start(); mt2.setName("B"); mt2.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { } // Thread.currentThread().getThreadGroup().interrupt(); } } class MyThread extends Thread { private Object lock; public MyThread(Object l) { this.lock = l; } public void run() { synchronized (lock) { System.out.println(getName() + " acquired lock"); try { lock.wait(); } catch (InterruptedException e) { System.out.println(getName() + " interrupted."); } System.out.println(getName() + " terminating."); } } } 

这是因为对lock.wait()的调用释放了锁,允许第二个线程进入synchronized块。 从javadoc中提取

该线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。 然后线程等待,直到它可以重新获得监视器的所有权并继续执行。

请注意,您的代码中存在一些问题,例如:

  • 你不应该在while循环之外等待
  • 没有任何通知,所以你的等待可以永远持续
  • 让你的任务实现Runnable并将其作为参数传递给Thread的构造函数而不是直接扩展Thread是一种更好的做法。

您应该使用同步阻止或等待呼叫。 一起使用它们是行不通的。 如果使用等待调用,则锁定由同步块中的对象释放。

所以删除行lock.wait ,你的程序将按你的意愿工作。 synchronize block将自动处理所有锁定。

如果您正在使用等待,那么必须使用通知。

这是关于这个的好主题: 为什么wait()总是在同步块中