Java自定义Cyclic Barrier中能否将sum/oldSum改为waitBarrier局部变量
答案
该需求完全可行,我们不仅可以将oldSum改为方法局部变量,甚至可以通过世代封装的方式,避免将sum作为类的顶层成员变量,最终实现和原有逻辑功能完全一致且线程安全。
实现原理
核心是引入*世代(Generation)*概念区分屏障的不同运行轮次:
- 每个轮次的累加和单独存储在对应世代实例中,不同轮次的累加数据完全隔离,不会互相覆盖
- 每个线程进入方法时将当前世代的引用存入自己的局部变量,后续操作都基于该局部引用
- 最后一个到达屏障的线程直接新建世代供下一轮使用,旧世代的累加结果不会被修改,所有线程都可以从自己持有的旧世代局部引用中拿到正确的总和返回,无需全局变量存储结果
具体实现代码
public class Barrier { private final int parties; private int partiesArrived = 0; // 内部类封装单轮屏障的状态,无需顶层sum、oldSum成员变量 private static class Generation { int sum = 0; } private Generation currentGen = new Generation(); public Barrier(int parties) { if (parties < 1) throw new IllegalArgumentException("Number of parties has to be 1 or higher."); this.parties = parties; } public int getParties() { return parties; } public synchronized int waitBarrier(int value) throws InterruptedException { // 当前世代引用存入局部变量 Generation gen = currentGen; gen.sum += value; partiesArrived += 1; // 返回值存储在局部变量,无需全局oldSum int result; if (partiesArrived != parties) { wait(); // 被唤醒后直接从局部持有的旧世代取总和,不会被新轮次修改 result = gen.sum; } else { result = gen.sum; // 新建世代供下一轮使用,旧世代数据保留 currentGen = new Generation(); partiesArrived = 0; notifyAll(); } return result; } public int getNumberWaiting() { return partiesArrived; } }
内容的提问来源于stack exchange,提问作者Augustinas Makevičius
相关产品推荐
相关产品推荐

