You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在类中创建含临界区的任务,是否存在竞态条件问题?

代码可行性分析与竞态条件验证

核心需求确认

  • 每次调用createTasks时生成独立新锁,锁不跨多次调用共享
  • 确保happenOnce方法在每批任务中仅执行一次
  • 完全避免竞态条件

基于需求的代码验证(假设你的实现符合如下核心逻辑)

先给出符合需求的参考实现(若你的实际代码与该逻辑一致,则完全可行):

public class TestConcurrency {
    public List<Runnable> createTasks() {
        // 每次调用创建全新锁实例,仅服务当前批次任务
        final Object batchLock = new Object();
        // 用数组存储执行标志,适配lambda对外部变量的访问规则
        final boolean[] hasExecuted = {false};

        List<Runnable> taskList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            taskList.add(() -> {
                // 业务逻辑前先处理happenOnce的执行控制
                synchronized (batchLock) {
                    if (!hasExecuted[0]) {
                        happenOnce();
                        hasExecuted[0] = true;
                    }
                }
                // 其他任务专属逻辑
                System.out.println("Task executed: " + Thread.currentThread().getName());
            });
        }
        return taskList;
    }

    private void happenOnce() {
        System.out.println("happenOnce executed by: " + Thread.currentThread().getName());
    }
}

// 调用方MyProgram代码
public class MyProgram {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        TestConcurrency concurrencyTest = new TestConcurrency();

        // 第一批任务:独立锁控制happenOnce执行一次
        threadPool.invokeAll(concurrencyTest.createTasks());
        // 第二批任务:全新锁,happenOnce再次执行一次
        threadPool.invokeAll(concurrencyTest.createTasks());

        threadPool.shutdown();
    }
}

可行性结论

1. 锁的隔离性满足要求

每次调用createTasks时,都会创建全新的batchLock实例,该锁仅绑定当前批次的任务集合,不会被后续createTasks调用生成的任务共享,完全符合“锁不跨多次调用共享”的要求。

2. 竞态条件完全避免

  • 通过synchronized(batchLock)实现了对hasExecuted标志的原子性检查与修改,同一批次的多个线程竞争锁时,只有第一个获取到锁的线程能执行happenOnce并将标志设为true,后续线程会直接跳过,无竞态风险。
  • 使用数组存储hasExecuted是正确的选择:lambda表达式只能访问外部的final或effectively final变量,数组可以在不改变引用的前提下修改内部值,避免编译错误和逻辑失效。

3. happenOnce执行次数严格受控

  • 同一批次的任务共享同一个锁和执行标志,确保happenOnce仅执行一次。
  • 不同批次的任务拥有独立的锁和标志,因此每调用一次createTasks并执行任务,happenOnce就会执行一次,完全符合预期。

潜在风险提示

  • 若将batchLock或hasExecuted声明为TestConcurrency类的成员变量,会导致锁和标志跨createTasks调用共享,直接违反需求,必须确保它们是createTasks方法内的局部变量。
  • 不要用普通布尔变量替代数组:普通布尔变量无法在lambda中修改,会引发编译错误或逻辑错误。

内容的提问来源于stack exchange,提问作者Elad Yehezkel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:01:01