持有多个锁的线程进入wait()状态。它是否释放所有锁定锁?

时间:2012-07-15 18:34:49

标签: java multithreading

我编写了这个程序来检查线程t1是否锁定了两个不同的对象: Lock.class和MyThread.class使用MyThread.class.wait()在MyThread.class实例上进入等待模式。它不会释放Lock.class实例上的锁。为什么这样 ?我一直在想,一旦一个线程进入等待模式或它死了,它就会释放所有获得的锁。

public class Lock {

protected static volatile boolean STOP = true;
public static void main(String[] args) throws InterruptedException {
    MyThread myThread = new MyThread();
    Thread t1 = new Thread(myThread);
    t1.start();
    while(STOP){
    }
    System.out.println("After while loop");
    /*
     * 
     */
    Thread.sleep(1000*60*2);
    /*
     * Main thread should be Blocked.
     */
    System.out.println("now calling Check()-> perhaps i would be blocked. t1 is holding lock on class instance.");
    check();
}

public static synchronized void check(){
    System.out.println("inside Lock.check()");
    String threadName = Thread.currentThread().getName();
    System.out.println("inside Lock.Check() method : CurrrentThreadName : "+ threadName);
}
}


class MyThread implements Runnable{
public MyThread() {
}

@Override
public void run() {
    try {
        System.out.println("inside Mythread's run()");
        classLocking();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public static synchronized void classLocking() throws InterruptedException{
    System.out.println("inside Mythread.classLocking()");
    String threadName = Thread.currentThread().getName();
    System.out.println("inside MyThread.classLocking() : CurrrentThreadName : "+ threadName);
    /*
     * outer class locking 
     */
    synchronized (Lock.class) {
        System.out.println("I got lock on Lock.class definition");
        Lock.STOP = false;
        /*
         * Outer class lock is not released. Lock on MyThread.class instance is released.
         */
        MyThread.class.wait();
    }
}
}

4 个答案:

答案 0 :(得分:4)

你没有释放其他锁是正确的。至于为什么,这是因为这样做是不安全的。如果在调用内部函数期间释放外部锁是安全的,为什么在保持另一个锁的情况下调用内部函数?

有一个函数释放一个锁,它没有在程序员的后面获取会破坏同步函数的逻辑。

答案 1 :(得分:0)

wait()的语义是调用它的线程注意到另一个线程已经获取了一个锁,被挂起并等待当后者释放它时持有锁的线程通知(并调用notify) 。这并不意味着在等待时释放所有获得的锁。您可以将等待调用视为线程在获取完成操作所需的所有锁定的路径上遇到的一些障碍。

关于“为什么一个线程不释放调用等待时获取的所有锁”的问题,我认为答案是这样做会使它更容易出现饥饿,并且还会减慢多线程的进度应用程序(所有线程在调用第一个等待时都会放弃所有锁定,并且当它们获得当前正在等待的锁定时必须重新启动。因此,它们将处于锁定的永久战斗中。 实际上,在这样的系统中,唯一能够完成执行的线程就是能够在需要时自由查找所有锁的线程。这不太可能发生)

答案 2 :(得分:0)

来自方法wait()

的JavaDoc
  

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

答案 3 :(得分:0)

是的,它运作正常。线程进入等待状态释放相应的锁而不是所有锁。否则考虑一下:如果事情就像你想的那样,那么当一个线程等待它就会丢失所有获得的锁,这使得高级顺序执行成为不可能。