直接上代码吧,这是一个小Demo,生产者和消费者
public class ThreadDemo17 {
public static void main(String[] args) {
Send send=new Send();
Rec rec=new Rec(send);
Thread t1=new Thread(send);
Thread t2=new Thread(rec);
t1.start();
t2.start();
}
}
class Send implements Runnable {
boolean flag;
int theValue;
public void run() {
for (int i = 1; i <= 2; i++) {
System.out.println("发送者循环"+i+"次");
synchronized (this) {
System.out.println("发送者进入同步快    flag="+flag);
while (flag) { // why需要用while 存在中断和虚假唤醒
try {
this.wait(); //wait方法会释放同步块的钥匙
System.out.println("发送者等待");
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
// 生产者生产食物
for(int j=1;j<=10;j++){
System.out.println("A线程循环"+j+"次");
}
// 自己去等待
flag = true;
this.notify(); //唤醒消费者
}
System.out.println("发送者释放同步块");
}
}
}class Rec implements Runnable {
private Send send; public Rec(Send send) {
super();
this.send = send;
} public void run() {
// 不知道生产者生产了多少食物,生产多少消费多少
for(int i=1;i<=2;i++) {
synchronized (send) {
System.out.println("接收者进入同步快    flag="+send.flag);
while (!send.flag) {
try {
send.wait();
System.out.println("发送者等待");
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//消费食物
for(int j=1;j<=20;j++){
System.out.println("B线程循环"+j+"次");
}
//自己去等待
send.flag=false;
send.notify();
}
} }}这段代码的开始运行结果是:
发送者循环1次
接收者进入同步快    flag=false
发送者进入同步快    flag=false
A线程循环1次
A线程循环2次
A线程循环3次
A线程循环4次
A线程循环5次
A线程循环6次
...
问题在于,代码中不是给接收者进行同步了吗(见代码synchronized (send){......}),相当于和发送者的synchronized (this)是加的同一把锁的,为什么接收者和发送者都可以进入同步快呢?

解决方案 »

  1.   

    这个问题的答案,你的代码里已经写好了:this.wait(); //wait方法会释放同步块的钥匙wait方法,会释放对象的同步锁,所以你下面的: synchronized (send) 就可以获取锁,进而继续执行了
    同理:send.wait();这句话同样会释放send所指向的对象的锁,自然,你前面的: synchronized (this) 也可以获取锁,继续执行了。因为,你的Send里的this与Rec里的send是指向同一个对象
      

  2.   

    嗯嗯,懂了。忘记了wait()方法会释放锁,不过你的顺序说错了,先进入接收者的线程,然后刚好flag初始值是false,所以它可以进入send.wait()释放锁,然后发送者线程才可以进入并锁住,循环打印10次,以此不会造成混乱,达到同步
      

  3.   

    sychonized只是一个同步锁,如果锁被释放,无论是消费者和生产者都能进入