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

Scala线程安全疑问:同步方法为何无法保证计数器输出稳定?

问题解析:线程执行顺序的不确定性与同步的作用边界

你的代码核心问题不是同步块无效,而是线程启动后执行顺序完全由操作系统调度决定,你默认认为t1、t2会先执行完再轮到t3,但实际情况并非如此。

具体原因:

  • increaseCounter()里的this.synchronized是有效的,它确保了counter += 1是原子操作,不会出现竞态条件导致的数值错误(比如两个线程同时读取counter=0,都加1后写回,结果还是1)。
  • 但你启动三个线程后,t1、t2、t3的执行顺序是不确定的:
    • 如果t3先被调度执行,此时t1和t2还没修改counter,输出就是0;
    • 如果t1执行完、t2还没开始时t3执行,输出就是1;
    • 只有当t1和t2都执行完毕后t3才执行,输出才是2。
  • 给printCounter()加同步也没用,因为同步只能保证读取counter时的可见性和原子性,无法改变线程的调度顺序。

解决方法:

要确保t3在t1和t2执行完成后再执行,需要在启动t3前调用t1.join()和t2.join(),让主线程等待这两个线程结束:

val t1: Thread = injectFunction(increaseCounter())
val t2: Thread = injectFunction(increaseCounter())
val t3: Thread = injectFunction(printCounter())
t1.start()
t2.start()
// 等待t1和t2执行完毕
t1.join()
t2.join()
t3.start()

这样修改后,每次输出都会是2。

补充细节:你的injectFunction参数是传名参数=> Unit,当前写法injectFunction(increaseCounter())是正确的——Scala传名参数的表达式会在被使用时才求值,也就是在线程run方法执行时才调用increaseCounter(),而非传递参数时立即执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 11:05:31