为什么Java中Thread类的start()方法是synchronized的?
Thread类的start()方法被设计为synchronized,核心是为了保障多线程环境下线程启动的安全性,具体原因可以分为这几点:
避免同一线程被重复启动
线程只有处于NEW状态时才能被启动,start()方法内部会先检查线程状态,若不是NEW则抛出IllegalThreadStateException。如果没有synchronized修饰,当多个线程同时调用同一个Thread实例的start()时,可能出现第一个线程刚通过状态检查、还没来得及修改线程状态,第二个线程也通过了检查的情况,进而导致多次触发底层的线程启动逻辑,这显然违反了线程只能启动一次的规则。synchronized保证了状态检查与后续启动操作的原子性,确保一个线程只会被启动一次。保证底层启动操作的原子性
start()最终会调用native的start0()方法,这个方法负责和JVM、操作系统交互,完成新线程的创建与调度。底层的线程创建逻辑并非线程安全的,synchronized可以避免多个线程同时触发同一Thread实例的底层启动流程,防止出现资源竞争或状态混乱。确保线程状态的可见性
synchronized的内存语义能保证:当一个线程调用start()修改了线程状态后,其他线程可以立即看到这个状态变更。如果没有同步,其他线程可能读取到线程的旧状态(比如仍为NEW),从而尝试再次启动线程,引发异常。
举个反例,如果start()不是synchronized:
Thread t = new Thread(() -> {}); // 两个线程同时调用t.start() new Thread(() -> t.start()).start(); new Thread(() -> t.start()).start();
这种场景下就可能出现两次调用start0()的情况,或者异常抛出时机不符合预期,而synchronized能从根本上避免这类问题。
内容的提问来源于stack exchange,提问作者chargedfever

