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

继承Thread类时同步机制失效,实现Runnable却正常,原因何在?

Java同步方法:继承Thread与实现Runnable的差异问题

问题描述

我在学习Java同步机制时,做同步方法练习发现一个问题——继承Thread类时没法得到正确的同步输出,但实现Runnable接口时同步功能完全正常,搞不懂原因,求解答。

代码实现

继承Thread类的实现

public class ClassRoom extends Thread {
    synchronized public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " enters class room");
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + " teaching students");
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + " exits class room");
        } catch(InterruptedException ie) {
            ie.getMessage();
        }
    }
}

实现Runnable接口的实现

public class ClassRoom implements Runnable {
    // 其余代码与继承Thread类的实现完全一致
    synchronized public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " enters class room");
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + " teaching students");
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + " exits class room");
        } catch(InterruptedException ie) {
            ie.getMessage();
        }
    }
}

继承Thread类的主方法

public class ClassRoomApp  {
    public static void main(String[] args) throws InterruptedException {
        ClassRoom physics_class = new ClassRoom();
        ClassRoom cs_class = new ClassRoom();
        ClassRoom english_class = new ClassRoom();
        
        physics_class.setName("Physics teacher");
        cs_class.setName("CS teacher");
        english_class.setName("English teacher");
        
        physics_class.start();
        cs_class.start();
        english_class.start();
    }
}

实现Runnable接口的主方法

public class ClassRoomApp  {
    public static void main(String[] args) throws InterruptedException {
        ClassRoom class_room = new ClassRoom();
    
        Thread t1 = new Thread(class_room);
        Thread t2 = new Thread(class_room);
        Thread t3 = new Thread(class_room);
            
        t1.setName("Physics teacher");
        t2.setName("CS teacher");
        t3.setName("English teacher");
    
        t1.start();
        t2.start();
        t3.start();
    }
}

输出情况

实现Runnable接口时的输出

Physics teacher enters class room
Physics teacher teaching students
Physics teacher exits class room
English teacher enters class room
English teacher teaching students
English teacher exits class room
CS teacher enters class room
CS teacher teaching students
CS teacher exits class room

继承Thread类时的输出

Physics teacher enters class room
English teacher enters class room
CS teacher enters class room
English teacher teaching students
Physics teacher teaching students
CS teacher teaching students
English teacher exits class room
CS teacher exits class room
Physics teacher exits class room

移除继承Thread类代码中的Thread.sleep()后的输出

  • 第一次输出(异常):
CS teacher enters class room
Physics teacher enters class room
Physics teacher teaching students
English teacher enters class room
Physics teacher exits class room
CS teacher teaching students
English teacher teaching students
CS teacher exits class room
English teacher exits class room
  • 第二次输出(看似正常):
Physics teacher enters class room
Physics teacher teaching students
Physics teacher exits class room
English teacher enters class room
English teacher teaching students
English teacher exits class room
CS teacher enters class room
CS teacher teaching students
CS teacher exits class room

问题原因分析

核心问题出在锁的对象不一致:

  1. 实现Runnable接口的场景:你只创建了一个ClassRoom实例,三个Thread线程共享这个实例。同步方法run()的锁是当前实例对象(也就是这个唯一的ClassRoom实例),所以三个线程会竞争同一把锁,必须等一个线程执行完释放锁后,另一个才能获取锁执行,自然实现了同步。
  2. 继承Thread类的场景:你创建了三个独立的ClassRoom实例(每个实例本身就是一个Thread对象)。每个线程的同步方法run()锁的是各自的实例对象(physics_class、cs_class、english_class三个不同对象)。三个线程各自持有自己的锁,互相不干扰,所以会同时执行,没有同步效果。

至于移除Thread.sleep()后有时出现看似正常的输出,那只是线程调度的巧合——某个线程可能刚好在其他线程完成启动前就执行完了整个run()方法,但本质上锁还是各自独立的,只要线程调度顺序稍有变化,输出就会乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:55:38