请按照以下代码
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'确实通知()但是代码仍处于同步块中,并且它仍然具有尚未释放的锁?
答案 0 :(得分:2)
答案在javadoc中。 Object#notify()
个州
唤醒的线程将无法继续直到当前 线程放弃对此对象的锁定。被唤醒的线程会 以通常的方式与任何其他可能的线程竞争 积极竞争同步这个对象;
所以你是对的。调用object.notify()
不会释放object
的监视器。它只是唤醒了一个仍然需要竞争才能获得它的线程。
因此notify()
不会释放监视器,但wait()
会释放监视器。
当前线程必须拥有此对象的监视器。 线程发布 此监视器的所有权,并等待另一个线程通知 在这个对象的监视器上等待的线程通过a唤醒 请致电
notify
方法或notifyAll
方法。
如果您对对象同步以及wait()
和notify()
的工作方式感到满意,请考虑转移到为您完成所有这些工作的java.util.concurrent
包。