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



请按照下面的代码操作,

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"中通知时,is会释放锁吗?

上述代码的输出是

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

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

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'没有notify(),但代码仍然在同步块中,并且它仍然有尚未释放的锁吗?

答案在javadoc中。Object#notify()状态

唤醒的线程将无法继续,直到当前线程放弃对此对象的锁定。唤醒的线程将以通常的方式与可能在该对象上主动竞争同步;

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

所以notify()不会释放监视器,但wait()会释放。

当前线程必须拥有此对象的监视器线程释放该监视器的所有权,并等待,直到另一个线程通知线程在该对象的监视器上等待通过调用CCD_ 6方法或CCD_。


当您对对象同步以及wait()notify()的工作方式感到满意时,可以考虑使用为您完成所有这些的java.util.concurrent包。

最新更新