2019-5-9问题的解决
今天又看了眼2019-5-9的问题,发现了问题的所在,关键在于 同步锁的对象(即monitor) 和 通信方法notifyAll() 的调用者要一致。
在前文失败的版本里,对Container的对象con加同步锁,却用消费者对象调用通信方法notifyAll(),显然不合适。
因此,这里改为 con.notifyAll() 。。问题解决。
同理,也可在Container的push()内部(同步块嵌套的外部方法)调用this.notifyAll();
修改后成功:
package mycode;
public class Cotest {
public static void main(String[] args) {
Container con = new Container();
new Provider(con).start();
new Customer(con).start();
}
}
//生产者
class Provider extends Thread{
Container con;
public Provider(Container con) {
super();
this.con = con;
}
public void run() {
for (int i = 1; i <= 100; i++) {
//管道已满 ,失败
synchronized (con) {
if(con.count == con.buns.length) {
try {
con.wait();//线程阻塞 消费者通知生产解除
} catch (InterruptedException e) {
System.out.println("生产者抛出异常");
}
}
Steamedbun bun = new Steamedbun(i);
System.out.println("生产-->第"+bun.id+"个包子");
con.push(bun);
con.notifyAll(); //也可在push();内部调用this.notifyAll();
}
}
System.out.println("生产完毕!!!!!!!!!!");
}
}
//消费者
class Customer extends Thread{
Container con;
public Customer(Container con) {
super();
this.con = con;
}
public void run() {
for (int i = 1; i <= 100; i++) {
//管道已空,失败
synchronized (con) {
if (con.count == 0) {
try {
con.wait();//线程阻塞 生产者通知消费解除
} catch (InterruptedException e) {
}
}
Steamedbun bun = con.pop();
System.out.println("消费-->第"+bun.id+"个包子");
con.notifyAll(); //也可在pop();内部调用this.notifyAll();
}
}
System.out.println("消费完毕!!!!!!!!!!");
}
}
//管道容器
class Container{
int count = 0; //包子个数
Steamedbun[] buns = new Steamedbun[10]; //容器
//生产包子
public void push(Steamedbun bun) {
buns[count]=bun;
count++;
//this.notifyAll();
}
//消费包子
public Steamedbun pop() {
count--;
//this.notifyAll();
return buns[count];
}
}
//包子
class Steamedbun{
int id;
public Steamedbun(int id) {
super();
this.id = id;
}
}
最后,我尝试将notifyAll()方法挪到同步块以外(同步块内嵌套的外部方法也算同步块的一部分),发现运行失败了,所以有空待验证以下命题:
对于加了同步锁的某个对象,其进程的通信方法notify必须放在同步块内。
Over~