需要一些解释我的等待和通知代码

时间:2014-01-06 15:44:59

标签: java multithreading thread-safety

请按照以下代码

Resource.java,

public class Resource {

public void first() {

    Thread t = Thread.currentThread();
    try {
        System.out.println(t.getName() + " : is accessing the method 'first' ");

        synchronized (this) {
            for (int num = 1; num <= 10; num++) {
                System.out.println(t.getName() + " : NUM : " + num);
                Thread.sleep(500);
                if (num == 5) {
                    this.wait();
                }
            }
            this.notify();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

public void second() {

    Thread t = Thread.currentThread();
    try {
        System.out.println(t.getName() + " : is accessing the method 'second' ");

        synchronized (this) {
            for (int num = 1; num <= 10; num++) {
                System.out.println(t.getName() + " : X : " + num);
                Thread.sleep(500);
                if (num == 7) {
                    this.notify();
                    this.wait();                       
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}
}

ReqThread.java如下,

public class ReqThread extends Thread{

public ReqThread(String name,Resource res){
    this.setName(name);
    this.res = res;
}

private Resource res;

@Override
public void run(){
    try{
        if("ONE".equals(this.getName())){
            res.first();
        }else{
            res.second();
        }            
    }catch(Exception e){
        e.printStackTrace();
    }
}
}

和MainClass.java,

public class MainClass {
public static void main(String [] args){
    Resource res = new Resource();
    ReqThread t1 = new ReqThread("ONE", res);
    ReqThread t2 = new ReqThread("TWO", res);

    t1.start();
    t2.start();
}
}

您可以从上面的代码中看到,我正在尝试使用等待和通知机制学习线程通信。

这里一个线程'ONE'首先启动,而计数器5等待并释放锁,然后线程'TWO'继续(已经处于等待状态)并且其计数器达到7通知并等待。

所以我的问题是当线程'TWO'在方法'second'中通知时,是否释放锁?

上述代码的输出是

ONE : is accessing the method 'first' 
ONE : NUM : 1
TWO : is accessing the method 'second' 
ONE : NUM : 2
ONE : NUM : 3
ONE : NUM : 4
ONE : NUM : 5
TWO : X : 1
TWO : X : 2
TWO : X : 3
TWO : X : 4
TWO : X : 5
TWO : X : 6
TWO : X : 7
ONE : NUM : 6
ONE : NUM : 7
ONE : NUM : 8
ONE : NUM : 9
ONE : NUM : 10
TWO : X : 8
TWO : X : 9
TWO : X : 10

现在,如果我在方法'second'中的Resource.java中进行代码更改,如下所示

if (num == 7) {
                    this.notify();
                    //this.wait();                       
                }

代码的输出是

ONE : is accessing the method 'first' 
ONE : NUM : 1
TWO : is accessing the method 'second' 
ONE : NUM : 2
ONE : NUM : 3
ONE : NUM : 4
ONE : NUM : 5
TWO : X : 1
TWO : X : 2
TWO : X : 3
TWO : X : 4
TWO : X : 5
TWO : X : 6
TWO : X : 7
TWO : X : 8
TWO : X : 9
TWO : X : 10
ONE : NUM : 6
ONE : NUM : 7
ONE : NUM : 8
ONE : NUM : 9
ONE : NUM : 10

从第二个输出中你可以看到,即使线程'TWO'确实通知(),它也不会等待并继续打印数字,

这是因为即使线程'TWO'确实通知()但是代码仍处于同步块中,并且它仍然具有尚未释放的锁?

1 个答案:

答案 0 :(得分:2)

答案在javadoc中。 Object#notify()个州

  

唤醒的线程将无法继续直到当前   线程放弃对此对象的锁定。被唤醒的线程会   以通常的方式与任何其他可能的线程竞争   积极竞争同步这个对象;

所以你是对的。调用object.notify()不会释放object的监视器。它只是唤醒了一个仍然需要竞争才能获得它的线程。

因此notify()不会释放监视器,但wait()会释放监视器。

  

当前线程必须拥有此对象的监视器。 线程发布   此监视器的所有权,并等待另一个线程通知   在这个对象的监视器上等待的线程通过a唤醒   请致电notify方法或notifyAll方法。


如果您对对象同步以及wait()notify()的工作方式感到满意,请考虑转移到为您完成所有这些工作的java.util.concurrent包。