使用不相关类的成员作为锁定对象时,同步块不起作用?

时间:2014-06-10 11:41:54

标签: java multithreading synchronization

我在同步块上找到的几乎所有资源都使用 this 或类的成员作为锁定对象。我有兴趣找出当锁对象是另一个类的(静态)成员时,为什么我不能使同步块工作。这是我的代码来说明问题:

public class Test {
        public static void main(String[] args) {
        Thread thread1 = new FirstThread();
        Thread thread2 = new SecondThread();
        thread1.start();
        thread2.start();
        }
    }

class FirstThread extends Thread {
    @Override
    public void run() {
        synchronized (Lock.lock) {
            System.out.println("First thread entered block");
            try {
                Lock.lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("First thread exited block");
    }
}

class SecondThread extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(1000); //just making sure second thread enters synch block after first thread
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (Lock.lock) {
            System.out.println("Second thread entered block");
            Lock.lock.notifyAll();
        }
        System.out.println("Second thread exited block");
    }
}

class Lock {
    public static Object lock = new Object();
}

我的理解是第二个线程在第一个线程退出之前不应该进入同步块,因为它们在同一个对象上同步。因此我期待程序在#34;第一个线程进入块"之后挂起(死锁?),因为第二个线程无法进入块并且第一个线程将被卡住等待通知。但我得到了以下输出:

First thread entered block

Second thread entered block

Second thread exited block

First thread exited block

显然,第二个线程在第一个线程离开它之前进入同步块。有人能解释我错过的东西吗? 我认为同步块的目的是为了防止这一点。是因为lock对象是另一个类的成员吗?

3 个答案:

答案 0 :(得分:3)

第一个线程Lock.lock.wait()放弃对同步对象的锁定,这样其他线程就可以进入关键路径并唤醒服务员。

请注意,sleep()不会。

Difference between wait() and sleep()

答案 1 :(得分:2)

来自javadoc of Object.wait()

的引用
  

线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。

如果不是这种情况,等待将系统地导致死锁,因为没有线程能够进入调用notify()notifyAll()所需的同步部分,等待并通知完全无用

答案 2 :(得分:1)

当您拨打锁定时,wait即可释放此监视器的所有权"。这允许线程2进入同步块。