首页 > 解决方案 > 实践中的 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

标签: javamultithreading

解决方案


每个线程的校验和是int sum. 这些中的每一个都被组合到最后putSumtakeSum最后。


推荐阅读