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

Java中同步块出现非预期输出的技术咨询

排查Java同步块的非预期输出问题

Hey,我来帮你搞定这个Java同步块导致的非预期输出问题!

首先,先把你没写完的代码补全为完整可运行的示例(这应该是你原本的代码结构):

class Table{
 public void printTbl(int n){
 //synchronize block
 synchronized(this){
 for(int i=1; i<11; i++){
 System.out.print(" "+i*n);
 try{
 Thread.sleep(600);
 }catch(Exception e){}
 }
 }//synchronize block end
 for(int j=0; j<5; j++){
 System.out.print(" "+Thread.currentThread().getName());
 try{
 Thread.sleep(1000);
 }catch(Exception e){}
 }
 }
}

class Table1 extends Thread{
 Table t;
 Table1(Table t){
 this.t = t;
 }
 public void run(){
 t.printTbl(5);
 }
}

class Table2 extends Thread{
 Table t;
 Table2(Table t){
 this.t = t;
 }
 public void run(){
 t.printTbl(10);
 }
}

public class TestSync{
 public static void main(String args[]){
 Table obj = new Table();//only one shared object
 Table1 t1=new Table1(obj);
 Table2 t2=new Table2(obj);
 t1.start();
 t2.start();
 }
}

问题根源

你遇到非预期输出的核心原因是:同步块只包裹了打印乘法表的第一个for循环,而打印线程名的第二个for循环没有被包含在同步块内。

当Thread-0(t1)执行完同步块里的乘法表循环后,会立即释放Table对象的锁,此时Thread-1(t2)就可以进入同步块执行自己的乘法表逻辑。但与此同时,Thread-0还在执行第二个打印线程名的循环,这就会导致两个线程的输出互相交错——比如你可能会看到 5 10 10 Thread-0 15...这类混乱的输出,而不是先完整打印完一个线程的乘法表+线程名,再轮到另一个线程。

修复方案

根据你的需求,有两种常见的修复方式:

方案1:让整个printTbl方法逻辑原子执行

如果你的需求是每个线程必须完整执行完printTbl的所有逻辑(乘法表+线程名),再轮到下一个线程,只需要把第二个for循环也放进同步块里即可:

class Table{
 public void printTbl(int n){
 // 同步块包裹整个方法的核心逻辑
 synchronized(this){
 for(int i=1; i<11; i++){
 System.out.print(" "+i*n);
 try{
 Thread.sleep(600);
 }catch(Exception e){}
 }
 // 将线程名循环移入同步块内
 for(int j=0; j<5; j++){
 System.out.print(" "+Thread.currentThread().getName());
 try{
 Thread.sleep(1000);
 }catch(Exception e){}
 }
 }//synchronize block end
 }
}

这样,同一时间只有一个线程能执行整个printTbl的逻辑,输出就会变成先完整打印Thread-0的乘法表+5次线程名,再打印Thread-1的对应内容,完全符合预期。

方案2:仅保证乘法表部分同步(如果业务允许线程名交错)

如果你的业务允许线程名的输出交错,但要求每个线程的乘法表必须完整打印完,再执行自己的线程名循环,也可以给线程名循环单独加锁(但方案1的写法更简洁高效)。不过这种场景比较少见,一般推荐方案1来保证逻辑的原子性。

补充说明

synchronized(this)是对当前Table实例对象加锁,所以只要多个线程共享同一个Table对象,同一时间只有一个线程能进入该同步块。你需要确保所有需要同步的逻辑都被包裹在这个锁范围内,否则就会出现线程安全问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:22:31