生産者と消費者とsynchronized 2008/03/25

Javaです。
生産者と消費者の実験のためのコード。

スタックに生産者がつんでいくのを消費者がpopして減らしていくというイメージ。
お互い壱秒休んで作業して休んで作業の繰り返しです。

import java.util.Stack;

public class TestT4 {
public static void main(String[] args) {

final Stack<Integer> stack = new Stack<Integer>();

Runnable consumer = new Runnable() {
public void run() {
while (true) {
sleep(1000);
synchronized (stack) {
if (!stack.isEmpty())
stack.pop();
}

}
}
};

Runnable producer = new Runnable() {
int cnt = 0;

public void run() {
while (true) {
sleep(1000);
synchronized (stack) {
stack.push(cnt++);
}

}
}
};

Runnable observer = new Runnable() {
public void run() {
while (true) {
sleep(1000);
System.out.println("" + stack);
}
}
};

new Thread(producer).start();
new Thread(producer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(observer).start();
}

static void sleep(long l) {
try {
Thread.sleep(l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


まずいコードです。
消費者の数が増える例外をだす可能性が増えます。
でる例外は、java.util.EmptyStackExceptionです。
stackが空ではなかったらpopするとしているのですが、空ではないと判断した直後で別の消費者がpopしてしまう可能性があります。
import java.util.Stack;

public class TestT4 {
public static void main(String[] args) {

final Stack<Integer> stack = new Stack<Integer>();

Runnable consumer = new Runnable() {
public void run() {
while (true) {
sleep(1000);
if (!stack.isEmpty())
stack.pop();
}
}
};

Runnable producer = new Runnable() {
int cnt = 0;
public void run() {
while (true) {
sleep(1000);
stack.push(cnt++);
}
}
};

Runnable observer = new Runnable() {
public void run() {
while (true) {
sleep(1000);
System.out.println("" + stack);
}
}
};

new Thread(producer).start();
new Thread(producer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(observer).start();
}

static void sleep(long l) {
try {
Thread.sleep(l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

: