请各位大虾帮忙解释一下,谢谢!程序片段如下:
------- SyncStack 类 -------------
public class SyncStack{
private Vector buffer = new Vector(400, 200);

public synchronized char pop(){
char c;
while (buffer.size() == 0){
try{
this.wait();
}catch (InterruptedException e){
// to do nothing
}
}
c = ((Character)buffer.remove(buffer.size() - 1)).charValue();
return c;
}

public synchronized void push(char c){
this.notify();
Character charObj = new Character(c);
buffer.addElement(charObj);
}
}---------- 生产者Producer类 ---------
public class Producer implements Runnable{
private SyncStack theStack;
public void run(){
char c;
for (int i = 0; i < 50; i++){
c = (char)(Math.random() * 26 + 'A');
theStack.push(c);
System.out.println("Producer" + num + ": " + c);
try{
Thread.sleep((int)(Math.random() * 300));
}catch (InterruptedException e){
//ignore this exception
}
}
}
}------ 消费者 Consumer类 --------------
public class Consumer implements Runnable{
private SyncStack theStack;
public void run(){
char c;

for (int i = 0; i<50; i++){
c = theStack.pop();
System.out.println("Consumer" + num + ": " + c);
try{
Thread.sleep((int)(Math.random() * 300));
}catch (InterruptedException e){
//ignore it
}
}
}
}------- 测试类 ----------------
public class SynchTest{
public static void main(String args[]){
SyncStack sStack = new SyncStack();

Producer p1 = new Producer(sStack);
Thread proT1 = new Thread(p1);  
proT1.start();

Producer p2 = new Producer(sStack);
Thread proT2 = new Thread(p2);
proT2.start();

Consumer c1 = new Consumer(sStack);
Thread conT1 = new Thread(c1);
conT1.start();

Consumer c2 = new Consumer(sStack);
Thread conT2 = new Thread(c2);
conT2.start();
}
程序运行结果片段如下:
Producer1: V
Producer2: R
Consumer1: R
Consumer2: V
Consumer2: Z
Producer2: Z
   
从程序代码看,很显然pop()只有在栈里有数据时才能执行,那么必然是push()被执行在先; 换句话说就是一定是先有producer,后有consumer。那么为什么这个结果里consumer在producer之前呢?请知道的说详细一点,告诉我,谢谢~

解决方案 »

  1.   

    出现这种情况是因为,
    你的producer和consumer中的打印语句并没有被synchronized
    也就是说,在producer push了一个字符后,还没有来的及打印“Producer:Z”,线程被切走(可以被切走因为这时已经出了同步块),customer执行pop(成功,因为栈上已经有东西),并且打印了“Consumer:Z”,这时切回线程Producer进程,执行打印语句“Producer:Z”