java - 实践中的 Java 并发“清单 12.5。BoundedBuffer 的生产者-消费者测试程序。”,每个线程的校验和?
问题描述
我正在阅读Java Concurrency in Practice并遇到以下代码片段。
// Listing 12.5. Producer-consumer test program for BoundedBuffer. I merge several "Listing"s and add some `printf` statements.
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class PutTakeTest {
private static final ExecutorService pool
= Executors.newCachedThreadPool();
private final AtomicInteger putSum = new AtomicInteger(0);
private final AtomicInteger takeSum = new AtomicInteger(0);
private final CyclicBarrier barrier;
private final BoundedBuffer<Integer> bb;
private final int nTrials, nPairs;
public static void main(String[] args) {
new PutTakeTest(10, 10, 100000).test(); // sample parameters
pool.shutdown();
}
PutTakeTest(int capacity, int npairs, int ntrials) {
this.bb = new BoundedBuffer<Integer>(capacity);
this.nTrials = ntrials;
this.nPairs = npairs;
this.barrier = new CyclicBarrier(npairs * 2 + 1);
}
void test() {
try {
for (int i = 0; i < nPairs; i++) {
pool.execute(new Producer());
pool.execute(new Consumer());
}
barrier.await(); // wait for all threads to be ready
barrier.await(); // wait for all threads to finish
System.out.printf("putSum.get() == takeSum.get(): %b\n", putSum.get() == takeSum.get());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
class Producer implements Runnable {
public void run() {
try {
System.out.printf("currentThread: %s, putSum: %s\n", Thread.currentThread().getName(), putSum.hashCode());
int seed = (this.hashCode() ^ (int) System.nanoTime());
int sum = 0;
barrier.await();
for (int i = nTrials; i > 0; --i) {
bb.put(seed);
sum += seed;
seed = xorShift(seed);
}
putSum.getAndAdd(sum);
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private int xorShift(int y) {
y ^= (y << 6);
y ^= (y >>> 21);
y ^= (y << 7);
return y;
}
}
class Consumer implements Runnable {
public void run() {
try {
System.out.printf("currentThread: %s, takeSum: %s\n", Thread.currentThread().getName(), takeSum.hashCode());
barrier.await();
int sum = 0;
for (int i = nTrials; i > 0; --i) {
sum += bb.take();
}
takeSum.getAndAdd(sum);
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
然后它说:
清单 12.5 和 12.6 中的 PutTakeTest 启动了 N 个生成元素并将它们入队的生产者线程,以及将它们出列的 N 个消费者线程。每个线程在元素进出时更新元素的校验和,使用在测试运行结束时组合的每个线程校验和,以便添加不超过测试缓冲区所需的同步或争用。
每线程校验和?我们只创建一个PutTakeTest
实例及其成员变量putSum
,并takeSum
在线程之间共享。这是一个错误吗?
// output
currentThread: pool-1-thread-1, putSum: 1211857397
currentThread: pool-1-thread-20, takeSum: 1616922032
currentThread: pool-1-thread-19, putSum: 1211857397
currentThread: pool-1-thread-18, takeSum: 1616922032
currentThread: pool-1-thread-17, putSum: 1211857397
currentThread: pool-1-thread-16, takeSum: 1616922032
currentThread: pool-1-thread-15, putSum: 1211857397
currentThread: pool-1-thread-14, takeSum: 1616922032
currentThread: pool-1-thread-13, putSum: 1211857397
currentThread: pool-1-thread-12, takeSum: 1616922032
currentThread: pool-1-thread-11, putSum: 1211857397
currentThread: pool-1-thread-10, takeSum: 1616922032
currentThread: pool-1-thread-9, putSum: 1211857397
currentThread: pool-1-thread-8, takeSum: 1616922032
currentThread: pool-1-thread-7, putSum: 1211857397
currentThread: pool-1-thread-6, takeSum: 1616922032
currentThread: pool-1-thread-5, putSum: 1211857397
currentThread: pool-1-thread-4, takeSum: 1616922032
currentThread: pool-1-thread-3, putSum: 1211857397
currentThread: pool-1-thread-2, takeSum: 1616922032
putSum.get() == takeSum.get(): true
解决方案
每个线程的校验和是int sum
. 这些中的每一个都被组合到最后putSum
或takeSum
最后。
推荐阅读
- php - phpmyadmin 使用 php 从多个表中选择数据
- sharepoint - 用于在桌面中打开 Visio 的 Office uri 架构
- python - Pandas DataRange 不包括其余的 excel 数据
- sql - 连接表时如何根据单条记录生成多行?
- python - 如何在pygame中修复阿拉伯语/波斯语文本和字体?
- python - 如何从熊猫数据框中逐句制作列表中的列表?
- neo4j - 在涉及多种类型时改进 neo4j 匹配
- python-3.x - 加快循环遍历两个大型(10000 秒)列表
- asp.net-core - ASP.NET Core 将 Web 应用程序部署到 aws ubuntu 服务器 18。除了没有 css、js、jquery 或引导程序之外,一切正常
- asp.net-mvc - 调试模式下的 ASP.NET 针对本地 SQL Server 2019 数据库获取随机超时