继承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
问题原因分析
核心问题出在锁的对象不一致:
- 实现Runnable接口的场景:你只创建了一个
ClassRoom实例,三个Thread线程共享这个实例。同步方法run()的锁是当前实例对象(也就是这个唯一的ClassRoom实例),所以三个线程会竞争同一把锁,必须等一个线程执行完释放锁后,另一个才能获取锁执行,自然实现了同步。 - 继承Thread类的场景:你创建了三个独立的
ClassRoom实例(每个实例本身就是一个Thread对象)。每个线程的同步方法run()锁的是各自的实例对象(physics_class、cs_class、english_class三个不同对象)。三个线程各自持有自己的锁,互相不干扰,所以会同时执行,没有同步效果。
至于移除Thread.sleep()后有时出现看似正常的输出,那只是线程调度的巧合——某个线程可能刚好在其他线程完成启动前就执行完了整个run()方法,但本质上锁还是各自独立的,只要线程调度顺序稍有变化,输出就会乱。
内容的提问来源于stack exchange,提问作者aMn
相关产品推荐
相关产品推荐

