Java线程干扰问题咨询:运行结果与预期不符的原因解析
问题解释
这两个异常都是线程干扰的典型表现,本质是:共享变量c的++/--操作并非原子性,而是拆分为「读取变量值→计算新值→写回变量」三步;同时操作系统会随机调度线程执行顺序,导致两个线程的指令交叉执行,最终出现不符合预期的结果。
关于第一个问题:1th decrement:(Retrieve C) 0
你预期读取值为-1,是假设t2线程第0次递减完成后,c会一直保持-1直到t2执行第1次递减,但实际线程调度完全随机:
假设执行顺序如下:
- t2完成第0次递减,将
c改为-1。 - 操作系统立刻切换到t1线程,t1执行一次递增操作,把
c从-1改回0。 - 切换回t2线程执行第1次递减,此时读取到的
c已经是0,就出现了你看到的打印结果。
关于第二个问题:递减后结果仍为-1
这是典型的更新丢失场景,核心是两个线程的修改互相覆盖:
假设执行顺序如下:
- t2读取
c=-1并打印,随后执行c--计算出-2,但还没来得及把新值写回内存。 - 操作系统切换到t1线程,t1读取当前内存中的
c=-1,执行递增后把c改为0并写回。 - 切换回t2线程,t2把之前计算的-2写回内存,但此时t1又快速执行了一次操作,把
c改回了-1。 - 最终t2打印递减后的
c值时,读取到的已经是被t1修改后的-1,而非自己计算的-2。
解决办法
要避免这类线程干扰问题,需要保证对共享变量的操作是原子性的,常用方案有两种:
- 用
synchronized关键字修饰increment和decrement方法,让同一时间只有一个线程能执行该方法。 - 使用
java.util.concurrent.atomic.AtomicInteger替代int类型,它提供了原子性的增减操作。
内容的提问来源于stack exchange,提问作者SB Lee
相关产品推荐
相关产品推荐

