Java 中生产者消费者问题中使用原子整数的奇怪输出
Strange output using Atomic Integer in Producer Consumer Problem in Java
在 Java 中使用 BlockingQueue 实现生产者-消费者问题时,使用 AtomicInteger 得到奇怪的输出,其中 2 个线程产生相同的结果并将相同的计数器变量放入队列中。考虑到 Atomic Integer 使用的比较和交换技术,该输出如何可能?
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class ProducerConsumer {
static BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(25);
static AtomicInteger counter=new AtomicInteger(0);
public static void main(String[] args) throws Exception{
Runnable producer = () -> {
while(!Thread.currentThread().isInterrupted()){
try {
final int e = counter.incrementAndGet();
queue.put(e);
if(e==26){
System.out.println("this is breaking the sequence...., value 26");
}
// System.out.println("Producer has produced the data:" +e);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ExecutorService producerPool = Executors.newFixedThreadPool(25);
for(int i=0; i<10;i++){
producerPool.submit(producer);
}
Thread.sleep(3000);
Scanner scanInput= new Scanner(System.in);
if(scanInput.next() != null){
producerPool.shutdownNow();
}
}
}
它产生如下输出,其中计数器达到 26
this is breaking the sequence...., value 26
在不同的 运行 中也可以产生以下结果:其中计数器仅达到 25,这是正确的
no output
我知道我没有使用任何同步来更新计数器值并将其放入队列,这将解决序列输出的问题,但我关心的是了解原子整数的工作原理,以及它为什么不工作适合这种场景。
对这种行为的任何想法。谢谢
截至目前,您正在使用其 toString
方法打印 AtomicInteger
值
"Producer has produced the data:" + Thread.currentThread().getName() + " : " + counter
您需要提取 AtomicInteger
值
final int e = counter.incrementAndGet();
queue.put(e);
System.out.println("Producer has produced the data:" + Thread.currentThread().getName() + " : " + e);
如果您之前没有提取它,在 toString
调用时该值可能已被另一个线程更新。它不再是 atomic。
在 Java 中使用 BlockingQueue 实现生产者-消费者问题时,使用 AtomicInteger 得到奇怪的输出,其中 2 个线程产生相同的结果并将相同的计数器变量放入队列中。考虑到 Atomic Integer 使用的比较和交换技术,该输出如何可能?
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class ProducerConsumer {
static BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(25);
static AtomicInteger counter=new AtomicInteger(0);
public static void main(String[] args) throws Exception{
Runnable producer = () -> {
while(!Thread.currentThread().isInterrupted()){
try {
final int e = counter.incrementAndGet();
queue.put(e);
if(e==26){
System.out.println("this is breaking the sequence...., value 26");
}
// System.out.println("Producer has produced the data:" +e);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ExecutorService producerPool = Executors.newFixedThreadPool(25);
for(int i=0; i<10;i++){
producerPool.submit(producer);
}
Thread.sleep(3000);
Scanner scanInput= new Scanner(System.in);
if(scanInput.next() != null){
producerPool.shutdownNow();
}
}
}
它产生如下输出,其中计数器达到 26
this is breaking the sequence...., value 26
在不同的 运行 中也可以产生以下结果:其中计数器仅达到 25,这是正确的
no output
我知道我没有使用任何同步来更新计数器值并将其放入队列,这将解决序列输出的问题,但我关心的是了解原子整数的工作原理,以及它为什么不工作适合这种场景。 对这种行为的任何想法。谢谢
截至目前,您正在使用其 toString
方法打印 AtomicInteger
值
"Producer has produced the data:" + Thread.currentThread().getName() + " : " + counter
您需要提取 AtomicInteger
值
final int e = counter.incrementAndGet();
queue.put(e);
System.out.println("Producer has produced the data:" + Thread.currentThread().getName() + " : " + e);
如果您之前没有提取它,在 toString
调用时该值可能已被另一个线程更新。它不再是 atomic。