多线程之间的友好通信-等待唤醒机制

时间:2023-02-12 14:33:07
线程之间的友好通信等待唤醒机制(wait\notify)
wait:调用wait方法,是当前线程从运行状态转变为阻塞状态,使用wait方法必须要有锁的支持,当前线程必须要有调用该方法的对象的监视器(也就是说该线程使用的同步锁必须与调用wait方法的对象保持一致)。
notify:唤醒拥有同一个监听器的其他同步线程(当然只会唤醒一个,由JVM决定);
错误代码:
class SubThread implements Runnable {

private Demo demo;

public SubThread(Demo demo) {
this.demo = demo;
}

@Override
public synchronized void run() {//错误原因:使用的是同步方法,该方法锁是:this
while (true) {
try {
if (demo.flag) {
demo.wait();//而这里却是demo对象
}

} catch (InterruptedException e) {
//
}
for (int i = 0; i < 10; i++) {
demo.i++;
System.out.println(Thread.currentThread().getName() + "----"
+ demo.i);
}

demo.flag = true;
demo.notify();
}

}

}
原因分析:
wait方法和notify方法,用于同一个监听器的同步线程,而同步方法的锁是当前对象,也就是SubThread对象。
wait和notify方法与同步方法使用的不是同一个锁,因此报如下错误:


Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.day27.test.SubThread.run(Test2.java:67)
at java.lang.Thread.run(Thread.java:619)



解决方法:使用同步代码块
如下:
class Test{

public static void main(String[] args) {
Demo demo = new Demo();
SubThread sub = new SubThread(demo);
Thread thread = new Thread(sub);
thread.start();

while (true) {
synchronized (demo) {//由于两个线程同步操作dmeo对象,因此两个线程的同步锁必须是同一个对象并且是demo
if (!demo.flag) {//当flag为false时,阻塞当前线程
try {
demo.wait();//由dmeo对象调用wait方法
} catch (InterruptedException e) {
// 
}
}

for (int i = 0; i < 100; i++) {
demo.i++;
System.out.println(Thread.currentThread().getName()
+ "----" + demo.i);
}

demo.flag = false;//执行完主线程,设置flag为false
demo.notify();//唤醒拥有同一个对象demo的监听器的其他同步线程
}

}

}
}


class Demo {
public boolean flag;//线程友好通信的标志
public int i;//两个线程共享的数据
}

class SubThread implements Runnable {

private Demo demo;

public SubThread(Demo demo) {
this.demo = demo;
}

@Override
public void run() {
while (true) {
synchronized (demo) {//同步锁对象
try {
if (demo.flag) {//当flag为true时,使子线程处于阻塞状态
demo.wait();//调用wait方法,是当前线程处于阻塞状态
}

} catch (InterruptedException e) {
//
}
for (int i = 0; i < 10; i++) {
demo.i++;
System.out.println(Thread.currentThread().getName()
+ "----" + demo.i);
}

demo.flag = true;//当子线程执行完成后,设置flag为true
demo.notify();//唤醒拥有同一个监视器的其他同步线程
}
}

}
}