Я видел фрагмент кода в этом question, который я не мог понять (скорее всего, из-за того, что я новичок в этой области). В этом вопросе говорится о «очевидном условиях гонки, где иногда продюсер заканчивает, сигнализирует об этом, а ConsumerWorkers останавливается, прежде чем потреблять все в очереди».В этом многопоточном java-коде есть действительно состояние гонки?
В моем понимании «isRunning» будет установлен на потребителей только после того, как производитель решает не добавлять больше элементов в очереди. Таким образом, если потребительский поток видит isRunning как FALSE, а затем видит, что inputQueue пуст, тогда нет никакой возможности добавить что-то в очередь в будущем. Obviosuly, я ошибаюсь и что-то не хватает, так как никто, кто ответил на этот вопрос, сказал, что сценарий вопроса невозможен. Итак, может ли кто-нибудь объяснить, какая последовательность событий вызывает это состояние гонки?
Фактически, я вижу проблему с чем-то еще. Например, если несколько потребительских потоков увидели, что производитель isRunning, и говорят, что очередь имеет ОДИН элемент, многие потоки могут войти в заблокированный «take». Если производитель STOPS теперь, а один поток выйдет из «take», , остальные потоки будут заблокированы на «take» навсегда. Интересно, что никто, кто ответил на этот вопрос, не указал на эту проблему. Итак, мое понимание этого также, вероятно, ошибочно?!
Я не хотел добавлять это как комментарий в этот вопрос, так как это старый вопрос, и мои сомнения никогда не получат ответа! Я скопирую/разместив код с этого вопроса здесь для быстрой справки.
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;
}
У меня была такая же мысль. И я проверил «редактирование» по этому вопросу, чтобы узнать, изменил ли ОП вопрос и модифицировал оператор. Но, он не имел. Этот оператор всегда был ||. И никто в этом не сомневался! – brainOverflow
это, вероятно, потому, что это не было необходимо, так как оба выражения ошибочны, было необходимо решение. Простой контроль действительно. – didierc