范例:
两个线程实现加法,两个线程实现减法
class Resource {
private int num = 0;
private boolean flag = true;
//flag = true 表示可以进行加法操作,不能进行减法操作
//flag = false 表示可以进行减法操作,不能进行加法操作
public synchronized void add() throws InterruptedException { //执行加法操作
if (this.flag == false) { //此处应使用while
super.wait();
}
Thread.sleep(100);
this.num++;
System.out.println(Thread.currentThread().getName() + " 加法操作 num = " + num);
this.flag = false;
super.notifyAll();
}
public synchronized void sub() throws InterruptedException { //执行减法操作
if (this.flag == true) { 此处应使用while
super.wait();
}
Thread.sleep(200);
this.num--;
System.out.println(Thread.currentThread().getName() + " 减法操作 num = " + num);
this.flag = true;
super.notifyAll();
}
}
class AddThread implements Runnable {
private Resource resource;
public AddThread(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
try {
this.resource.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class SubThread implements Runnable {
private Resource resource;
public SubThread(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
try {
this.resource.sub();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Resource resource = new Resource();
AddThread addThread = new AddThread(resource);
SubThread subThread = new SubThread(resource);
new Thread(addThread, "加法线程 - A").start();
new Thread(addThread, "加法线程 - B").start();
new Thread(subThread, "减法线程 - X").start();
new Thread(subThread, "减法线程 - Y").start();
}
}
此代码中有一个问题,数字num会出现一直减一直加的问题,是因为在进行线程同步时,多个线程都通过wait()方法进入阻塞状态后,当一个线程通过notifyAll唤醒其余的线程后,阻塞状态的线程就会直接继续往下执行,所以无法实现线程同步。解决思路是线程从阻塞状态被唤醒后必须再次检验flag的值。
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout, nanos);
... // Perform action appropriate to condition
}
上面是官方文档的说明
所以只需要把if改成while就可以了