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

Java多线程:共享char数组是否会因竞态条件出现异常输出?

共享数组修改后的可见性问题解答

先直接给你吃个定心丸:你的代码绝对不会输出'aB'或'bA',最终一定会打印'AB'。下面来拆解背后的原因,包括你关心的JMM规则和缓存行疑问:

1. Future.get()触发的Happens-Before关系是核心

Java内存模型(JMM)里的happens-before规则直接解决了你的可见性担忧:

  • 当你调用f1.get()并成功返回时,JMM会强制保证:f1对应的任务里的所有操作(也就是shared[0] = 'A'),都绝对先于当前线程后续的任何操作执行完成,并且所有修改都同步到了主内存。
  • 同理,f2.get()返回后,f2任务的修改(shared[1] = 'B')也会完全同步,并且先于后续的打印操作。

这意味着,当你执行System.out.println(shared)时,两个任务对数组的修改已经100%对当前线程可见,所以输出必然是AB。

2. 缓存行刷新不会导致“陈旧字节覆盖”

你担心的“同一缓存行里的相邻字节被陈旧数据覆盖”是不会发生的:

  • 现代CPU的缓存一致性协议(比如MESI)会妥善处理同一缓存行内不同字节的独立修改:线程修改某一字节后,缓存系统只会标记该字节所在的缓存行为“脏”,同步时只会把修改过的字节更新到主内存,不会覆盖其他线程已经修改的相邻字节。
  • 退一步说,JMM本身已经通过happens-before规则屏蔽了底层缓存的细节——不管缓存怎么刷新,只要满足规则,你就能保证操作的可见性和正确性,不用纠结底层的缓存实现。

额外提一句:如果去掉get()会怎样?

要是你的代码没调用f1.get()和f2.get(),直接打印数组,那确实可能出现aB、bA甚至ab的情况,因为此时没有同步机制保证任务的修改对当前线程可见。但你的代码里明确等待了两个任务完成,所以完全没这个风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:07:34