两个线程如何进入两个同步块,这些块在同一个对象上保持锁定

时间:2016-07-27 20:54:18

标签: java multithreading synchronized

我有一些像这样的代码:

ON DELETE CASCADE

Class ThreadB:

public class HelloWorld {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        Runnable a = new Runnable(){
            public void run(){
                System.out.println(Thread.currentThread().getId());
                synchronized(b){
                    try{
                        System.out.println("Waiting for b to complete...");
                        b.wait();
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println("Total is: " + b.total);
                }
            }
        };

        (new Thread(a)).start();

        synchronized(b){
            System.out.println(Thread.currentThread().getId());
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
}

基本上,我有两个线程锁定Threadb对象b。当我运行代码时,我看到:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            System.out.println("Total is: " + total);
            notify();
        }
    }
}

这里,数字是线程ID,很明显,它们是不同的线程。 此外,它们锁定的对象是相同的(b)。但是,两者都能够进入同步块并等待对象。

怎么可能?

此外,如果我在threadB.run()方法中插入2个其他行:

1
Waiting for b to complete... 
22
Waiting for b to complete...

2个线程运行完成:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            System.out.println("Total is: " + total);
            notify();
        }
    }
}

似乎在ThreadB.run()的旧定义中,等待线程错过了通知信号,因此它们无限期地等待。这是对的吗?

此外,如果一个线程在没有调用notify()的情况下退出,则内部释放锁(相当于notifyAll())。是吗?

1 个答案:

答案 0 :(得分:5)

因为调用Object.wait()会释放锁定。来自the documentation

  

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

  1. 似乎在ThreadB.run()的旧定义中,等待线程错过了通知信号,因此它们无限期地等待。这是正确的吗? 他们wait()直到他们notify()'(可能发生虚假)或者他们被打断。

  2. 此外,如果线程退出而未调用notify(),则内部释放锁(相当于notifyAll())。是吗? 线程wait()后,锁已经被释放。

相关问题