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

为何调用synchronized方法未阻塞MyThread对象?

Synchronized方法的理解误区解析

问题描述

调用mt1.method()时预期会阻塞MyThread对象,但实际并未发生。当run方法中使用普通for循环时,主线程与Thread-0交替执行;若将run方法中的for循环替换为调用synchronized修饰的method(),则会按预期顺序执行。请问对synchronized方法的理解哪里有误?

相关代码

class MyThread implements Runnable {
    public Thread thrd;

    public MyThread() {
        thrd = new Thread(this);
    }

    public static MyThread createAndRun() {//Test t
        MyThread mt = new MyThread();
        mt.thrd.start();
        return mt;
    }

    @Override
    public void run() {
// This way main thread doesn't block MyThread.
        for (int i = 0; i < 10; ++i) {
            System.out.print(Thread.currentThread().getName() + ":" + i + " ");

            try {
                Thread.sleep(250);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
        }
//main:0 Thread-0:0 main:1 Thread-0:1 main:2 Thread-0:2 main:3 Thread-0:3 main:4 Thread-0:4 main:5 Thread-0:5 Thread-0:6 main:6 Thread-0:7 main:7 Thread-0:8 main:8 Thread-0:9 main:9 





//        method();// if use it instead for-lopp - all works as expected. 
//main:0 main:1 main:2 main:3 main:4 main:5 main:6 main:7 main:8 main:9 Thread-0:0 Thread-0:1 Thread-0:2 Thread-0:3 Thread-0:4 Thread-0:5 Thread-0:6 Thread-0:7 Thread-0:8 Thread-0:9 
    }

    synchronized public void method() {
        for (int i = 0; i < 10; ++i) {
            System.out.print(Thread.currentThread().getName() + ":" + i + " ");
            try {
                Thread.sleep(250);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
        }
    }
}

class App {
    public static void main(String[] args) {
        MyThread mt1 = MyThread.createAndRun();
        mt1.method();
        try {
            mt1.thrd.join();
        } catch (InterruptedException exc) {
            System.out.println(exc);
        }
    }
}

误区解析

核心错误是误以为synchronized会锁住整个对象,阻止其他线程执行该对象的所有代码,但实际上synchronized只保护被它修饰的代码块/方法,未被同步的代码不受锁的约束:

  • 当run方法使用普通for循环时,这个循环没有被同步锁保护。主线程调用mt1.method()时,虽然拿到了mt1对象的锁,但Thread-0执行的是无锁的for循环,完全不受锁的影响,两个线程各自独立执行,因此出现交替输出的情况。
  • 当run方法替换为调用method()时,Thread-0要执行这个同步方法,必须先获取mt1对象的锁。而主线程已经先调用了mt1.method()并持有锁,直到主线程执行完method()才会释放锁。Thread-0只能等待锁释放后才能执行,因此出现主线程先输出完毕,再轮到Thread-0输出的顺序。

简言之:synchronized的作用范围仅限于被它修饰的代码,不是对整个对象的全局阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:20:23