我想在 Java 中使用生产者-消费者模型将竞争条件复制到死锁
I want to replicate race condition into deadlock using the Producer-Consumer model in Java
在 wiki 上,我发现了以下生产者-消费者程序的伪代码,它具有可能导致死锁的竞争条件:
int itemCount = 0;
procedure producer()
{
while (true)
{
item = produceItem();
if (itemCount == BUFFER_SIZE)
{
sleep();
}
putItemIntoBuffer(item);
itemCount = itemCount + 1;
if (itemCount == 1)
{
wakeup(consumer);
}
}
}
procedure consumer()
{
while (true)
{
if (itemCount == 0)
{
sleep();
}
item = removeItemFromBuffer();
itemCount = itemCount - 1;
if (itemCount == BUFFER_SIZE - 1)
{
wakeup(producer);
}
consumeItem(item);
}
}
使用此实现,应该会出现以下情况:
消费者刚刚读取了变量 itemCount,注意到它为零并且正要移动到 if 块内。
就在调用睡眠之前,消费者被中断,生产者被恢复。
生产者创建一个item,放入buffer,增加itemCount。
因为缓冲区在最后一次添加之前是空的,所以生产者试图唤醒消费者。
不幸的是消费者还没有睡觉,叫醒电话丢失了。当消费者恢复时,它进入休眠并且永远不会再被唤醒。这是因为消费者只有在itemCount等于1时才会被生产者唤醒。
生产者会一直循环直到缓冲区满,之后它也会进入休眠
我希望能够在 Java 中复制它,但到目前为止我无法在 运行 我的程序之后多次复制。这是我的代码:
private LinkedList<Integer> sharedList = new LinkedList<Integer>();
private int sharedValue = 0;
private int MAX_LIMIT = 10;
public void produce() throws InterruptedException {
Random random = new Random();
while (true) {
synchronized (this) {
if (sharedValue == MAX_LIMIT) { //'produce' thread waits if list is full
wait();
}
sharedValue = sharedValue + 1;
sharedList.add(sharedValue); System.out.println("added value: " + sharedValue);
if (sharedValue == 1) {
notify(); //notifies 'consume' thread if list is not empty
}
}
}
}
public void consume() throws InterruptedException {
Random random = new Random();
while (true) {
synchronized (this) {
if (sharedValue == 0) { //'consume' waits if list is empty
wait();
}
sharedValue = sharedValue - 1;
sharedList.remove(); System.out.println("removed value: " + sharedValue);
if (sharedValue == MAX_LIMIT-1) {
notify(); //notifies 'produce' if list is not full
}
}
Thread.sleep(random.nextInt(1000));
}
}
原因是您同步了整个迭代步骤。 synchronized (this) {...}
下的两个代码块将依次 运行。
您可以复制它:
private LinkedList<Integer> sharedList = new LinkedList<Integer>();
private volatile int sharedValue = 0;
private int MAX_LIMIT = 10;
public void produce() throws InterruptedException {
while (true) {
if (sharedValue == MAX_LIMIT) { //'produce' thread waits if list is full
synchronized (this) {
wait();
}
}
synchronized (this) {
sharedValue = sharedValue + 1;
sharedList.add(sharedValue);
System.out.println("added value: " + sharedValue);
}
if (sharedValue == 1) {
synchronized (this) {
notify(); //notifies 'consume' thread if list is not empty
}
}
}
}
public void consume() throws InterruptedException {
while (true) {
if (sharedValue == 0) { //'consume' waits if list is empty
synchronized (this) {
wait();
}
}
synchronized (this) {
sharedValue = sharedValue - 1;
sharedList.remove();
System.out.println("removed value: " + sharedValue);
}
if (sharedValue == MAX_LIMIT - 1) {
synchronized (this) {
notify(); //notifies 'produce' if list is not full
}
}
}
}
在 wiki 上,我发现了以下生产者-消费者程序的伪代码,它具有可能导致死锁的竞争条件:
int itemCount = 0;
procedure producer()
{
while (true)
{
item = produceItem();
if (itemCount == BUFFER_SIZE)
{
sleep();
}
putItemIntoBuffer(item);
itemCount = itemCount + 1;
if (itemCount == 1)
{
wakeup(consumer);
}
}
}
procedure consumer()
{
while (true)
{
if (itemCount == 0)
{
sleep();
}
item = removeItemFromBuffer();
itemCount = itemCount - 1;
if (itemCount == BUFFER_SIZE - 1)
{
wakeup(producer);
}
consumeItem(item);
}
}
使用此实现,应该会出现以下情况:
消费者刚刚读取了变量 itemCount,注意到它为零并且正要移动到 if 块内。
就在调用睡眠之前,消费者被中断,生产者被恢复。
生产者创建一个item,放入buffer,增加itemCount。
因为缓冲区在最后一次添加之前是空的,所以生产者试图唤醒消费者。
不幸的是消费者还没有睡觉,叫醒电话丢失了。当消费者恢复时,它进入休眠并且永远不会再被唤醒。这是因为消费者只有在itemCount等于1时才会被生产者唤醒。
生产者会一直循环直到缓冲区满,之后它也会进入休眠
我希望能够在 Java 中复制它,但到目前为止我无法在 运行 我的程序之后多次复制。这是我的代码:
private LinkedList<Integer> sharedList = new LinkedList<Integer>();
private int sharedValue = 0;
private int MAX_LIMIT = 10;
public void produce() throws InterruptedException {
Random random = new Random();
while (true) {
synchronized (this) {
if (sharedValue == MAX_LIMIT) { //'produce' thread waits if list is full
wait();
}
sharedValue = sharedValue + 1;
sharedList.add(sharedValue); System.out.println("added value: " + sharedValue);
if (sharedValue == 1) {
notify(); //notifies 'consume' thread if list is not empty
}
}
}
}
public void consume() throws InterruptedException {
Random random = new Random();
while (true) {
synchronized (this) {
if (sharedValue == 0) { //'consume' waits if list is empty
wait();
}
sharedValue = sharedValue - 1;
sharedList.remove(); System.out.println("removed value: " + sharedValue);
if (sharedValue == MAX_LIMIT-1) {
notify(); //notifies 'produce' if list is not full
}
}
Thread.sleep(random.nextInt(1000));
}
}
原因是您同步了整个迭代步骤。 synchronized (this) {...}
下的两个代码块将依次 运行。
您可以复制它:
private LinkedList<Integer> sharedList = new LinkedList<Integer>();
private volatile int sharedValue = 0;
private int MAX_LIMIT = 10;
public void produce() throws InterruptedException {
while (true) {
if (sharedValue == MAX_LIMIT) { //'produce' thread waits if list is full
synchronized (this) {
wait();
}
}
synchronized (this) {
sharedValue = sharedValue + 1;
sharedList.add(sharedValue);
System.out.println("added value: " + sharedValue);
}
if (sharedValue == 1) {
synchronized (this) {
notify(); //notifies 'consume' thread if list is not empty
}
}
}
}
public void consume() throws InterruptedException {
while (true) {
if (sharedValue == 0) { //'consume' waits if list is empty
synchronized (this) {
wait();
}
}
synchronized (this) {
sharedValue = sharedValue - 1;
sharedList.remove();
System.out.println("removed value: " + sharedValue);
}
if (sharedValue == MAX_LIMIT - 1) {
synchronized (this) {
notify(); //notifies 'produce' if list is not full
}
}
}
}