4

我看不到以下代码如何产生似乎违反对象锁定义的输出。当然应该只允许一个线程打印“获得的锁”消息,但他们都这样做吗?

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.");
        }
    }
}
4

2 回答 2

7

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

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

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

  • 你不应该在while循环之外等待
  • 任何地方都没有通知,因此您的等待可能会永远持续下去
  • 让您的任务实现 Runnable 并将其作为参数传递给 Thread 的构造函数比直接扩展 Thread 更好。
于 2013-01-23T17:01:23.573 回答
0

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

因此,删除该行lock.wait,您的程序将按您的意愿运行。同步块将自动处理所有锁。

如果您使用等待,则必须使用通知。

这是一个很好的线程:Why must wait() always be in synchronized block

于 2013-01-23T17:07:05.917 回答