虽然以下是众所周知的话题,但我想要你的想法。 我写了一个小程序如下:所有的生产者排队等候消费者。我不明白为什么会这样。它可以完全阻止的场景是什么。
让我们考虑生产者/消费者正在等待锁定阵列以及使消费者/生产者退出同步块的原因。我的意思是它必须缓慢移动,但绝不能发生死锁。我相信。
这里我有两个问题: 1.发生死锁的场景是什么? 2.如何理解引擎盖下发生的事情。我的意思是如何调试。
public class ProducerConsumer implements Runnable {
boolean producer = false;
private volatile int i = 0;
int[] array = new int[10];
public static String getThreadName() {
return Thread.currentThread().getName();
}
public void producer() {
try {
synchronized (array) {
while (i > 9) {
System.out.println("Producer of " + getThreadName()
+ " is waiting i " + i);
array.wait();
System.out.println("Producer of " + getThreadName()
+ " came out of sleep i " + i);
}
System.out.println("Producer of " + getThreadName()
+ " in synchronized block i" + i);
array[i] = generateRandom();
System.out.println("Producer of " + getThreadName()
+ " inserted in array " + array[i] + " index " + i);
i++;
array.notifyAll();
}
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Producer of " + getThreadName()
+ " interrupted " + e);
}
}
public void consumer() {
try {
synchronized (array) {
while (i < 0) {
System.out.println("Consumer of " + getThreadName()
+ " is waiting i " + i);
array.wait();
System.out.println("Consumer of " + getThreadName()
+ " came out of sleep i " + i);
}
System.out.println("Consumer of " + getThreadName()
+ " in synchronized block extracted value " + array[i]
+ " of index " + i);
i--;
array.notifyAll();
}
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Consumer of " + getThreadName()
+ " interrupted " + e);
}
}
public static int generateRandom() {
Random random = new Random();
return random.nextInt(10);
}
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
for (int i = 0; i < 4; i++) {
if (i % 2 == 0)
new Thread(pc, "producer thread").start();
else {
new Thread(pc, "consumer thread").start();
}
}
}
public void run() {
while (true) {
if (getThreadName().equalsIgnoreCase("producer thread")) {
producer();
} else {
consumer();
}
}
}
}
如下所示:
Consumer of consumer thread in synchronized block extracted value 0 of index 0
Producer of producer thread in synchronized block i-1
Producer of producer thread in synchronized block i-1
Consumer of consumer thread is waiting i -1
Consumer of consumer thread is waiting i -1
答案 0 :(得分:2)
您的代码在许多地方都不正确。
我希望所有线程都能完成异常,因为
您检查过错误输出吗?
答案 1 :(得分:0)
Java通过其java.util.concurrent
包提供了一个简洁的并发程序实现。因此,您应该使用Concurrent API
以更安全的方式处理锁定,而不是尝试重新发明轮子并将其全部弄错。这是Producer-Consumer
的模拟:
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* We want a Producer thread to create random values, and the Consumer thread to
* consume it. One caveat is that if the Producer has already created a random
* value, which the Consumer thread hasn't consumed yet, the Producer thread
* blocks or waits. On the flip side, the Consumer thread waits for the Producer
* thread to produce some value if the Producer thread hasn't already.
* <p/>
* Write a Program to simulate such a situation.
*/
public class ProducerConsumerCommunication
{
private volatile boolean running = true;
private ArrayBlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(1);
private Random random = new Random(System.currentTimeMillis());
public ProducerConsumerCommunication()
{
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new ProducerTask());
service.execute(new ConsumerTask());
service.shutdown();
}
public static void main(String[] args)
{
new ProducerConsumerCommunication();
}
private class ProducerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = random.nextInt();
buffer.put(value); // Blocks if buffer is full.
System.out.println("Value Put: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
private class ConsumerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = buffer.take(); // Blocks if buffer is empty.
System.out.println("Value Taken: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
尝试运行它并亲自了解使用Concurrent API实现此类方案的简单性和直观性。它还可以保持代码清洁,让您专注于手头的问题。
Producer Consumer
问题死锁的原因并不多。如果一个线程锁定object A
并等待object B
上的锁被释放,而其他线程同时锁定object B
并等待锁定{ {1}}被释放,出现了僵局。