6

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

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

4 回答 4

4

你是对的,它不会释放另一个锁。至于为什么,那是因为这样做不安全。如果在调用内部函数的过程中释放外部锁是安全的,那么为什么调用内部函数时完全持有另一个锁呢?

让函数释放它没有在程序员背后获得的锁会破坏同步函数的逻辑。

于 2012-07-15T18:44:42.857 回答
0

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

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

于 2012-07-15T18:45:21.467 回答
0

来自方法的JavaDocwait()

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

于 2012-07-15T18:48:01.217 回答
0

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

于 2012-07-15T18:49:31.603 回答