这个多线程java代码中真的存在竞争条件吗?
我在这篇文章中看到了一段我无法理解的代码(很可能是因为我是这方面的初学者)。该问题涉及到“一种明显的竞赛状态,有时制作人会结束比赛,发出信号,而消费工人会在消费完队列中的所有东西之前停止比赛。”这个多线程java代码中真的存在竞争条件吗?,java,multithreading,synchronization,race-condition,producer-consumer,Java,Multithreading,Synchronization,Race Condition,Producer Consumer,我在这篇文章中看到了一段我无法理解的代码(很可能是因为我是这方面的初学者)。该问题涉及到“一种明显的竞赛状态,有时制作人会结束比赛,发出信号,而消费工人会在消费完队列中的所有东西之前停止比赛。” 据我所知,只有在生产商决定不再在队列中添加任何项目后,才会对消费者设置“isRunning”。因此,如果使用者线程将isRunning视为FALSE,然后将inputQueue视为空,则将来不可能再向队列中添加任何内容。 很明显,我错了,遗漏了一些东西,因为回答这个问题的人都说这个问题的情景是不可能的。
public class ConsumerWorker implements Runnable{
private BlockingQueue<Produced> inputQueue;
private volatile boolean isRunning = true;
public ConsumerWorker(BlockingQueue<Produced> inputQueue) {
this.inputQueue = inputQueue;
}
@Override
public void run() {
//worker loop keeps taking en element from the queue as long as the producer is still running or as
//long as the queue is not empty:
while(isRunning || !inputQueue.isEmpty()) {
System.out.println("Consumer "+Thread.currentThread().getName()+" START");
try {
Object queueElement = inputQueue.take();
//process queueElement
} catch (Exception e) {
e.printStackTrace();
}
}
}
//this is used to signal from the main thread that he producer has finished adding stuff to the queue
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
公共类ConsumerWorker实现可运行{
私有阻塞队列输入队列;
private volatile boolean isRunning=true;
公共消费器工作者(阻止队列输入队列){
this.inputQueue=inputQueue;
}
@凌驾
公开募捐{
//只要生产者仍在运行,工作循环就一直从队列中获取en元素,或者
//只要队列不是空的:
同时(正在运行| |!inputQueue.isEmpty()){
System.out.println(“使用者”+线程.currentThread().getName()+开始”);
试一试{
Object queueElement=inputQueue.take();
//进程队列元素
}捕获(例外e){
e、 printStackTrace();
}
}
}
//这用于从主线程发出信号,表示生产者已完成向队列添加内容
公共void setRunning(布尔值isRunning){
this.isRunning=isRunning;
}
我认为原始问题的OP可能意味着
while(isRunning && !inputQueue.isEmpty())
而不是
while(isRunning || !inputQueue.isEmpty())
前者显然产生了原始海报(*)中描述的问题,而后者确实存在您在第二点中描述的问题。这是一个简单的疏忽,但现在我们可以注意到这两种方法都是不正确的
(*)并以某种方式假设队列永远不会为空。我认为原始问题的OP可能意味着
while(isRunning && !inputQueue.isEmpty())
而不是
while(isRunning || !inputQueue.isEmpty())
前者显然产生了原始海报(*)中描述的问题,而后者确实存在您在第二点中描述的问题。这是一个简单的疏忽,但现在我们可以注意到这两种方法都是不正确的
(*)并以某种方式假设队列永远不会为空。你在两个问题上都是正确的。&&是正确的,
|
不是。至于第二个问题,答案是使用毒药丸
或超时,这两种方法都可以解决问题
对于我来说,我将创建一个新的同步类来聚合队列和
isRunning
变量,这样更改isRunning
会导致take()中出现异常
因此表示工作结束。你在这两个问题上都是正确的。是的&&
是正确的,|
不是。至于第二个问题,答案是使用毒药丸
或超时,这两种方法都可以解决问题
对于我来说,我将创建一个新的同步类来聚合队列和
isRunning
变量,这样更改isRunning
会导致take()中出现异常
这样就意味着工作结束了。我也有同样的想法。我确实检查了对该问题的“编辑”,看看OP是否更改了该问题并修改了运算符。但是,他没有。该运算符始终是| |。该qn中没有人对此提出质疑!这可能是因为没有必要,因为这两个表达式都是错误的,一个解决方案离子是必要的。一个简单的疏忽真的。我也有同样的想法。我确实检查了这个问题的“编辑”,看看OP是否改变了这个问题并修改了操作符。但是,他没有。这个操作符总是| |。那个qn中没有人质疑这个!这可能是因为它没有必要,因为两个表达式都是错误的,一个解决方案这是必要的。一个简单的疏忽。我实际上最喜欢@PeterLawrey的回应。但那就是我。我实际上最喜欢@PeterLawrey的回应。但那就是我。