Java中继承Thread类本身不会导致死锁,真正引发死锁的是run()方法中对共享资源的不安全访问;防范措施包括统一锁获取顺序(如按System.identityHashCode排序)、避免嵌套加锁和持有锁调用外部方法。

Java 中继承 Thread 类本身不会导致死锁,真正引发死锁的是线程在执行逻辑时对共享资源(尤其是多个锁)的不安全访问方式。继承 Thread 只是定义线程的一种形式,关键在于 run() 方法里是否出现锁顺序混乱、嵌套加锁、持有锁调用外部方法等高危行为。
下面从实际编码角度给出具体、可落地的防范措施:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
统一锁获取顺序
多个线程若需同时操作多个对象(如两个账户转账),必须强制按固定规则排序后再加锁,打破“循环等待”条件。 例如用对象身份哈希值(避免 `hashCode()` 被重写干扰):if (System.identityHashCode(from)
synchronized (from) {
synchronized (to) { /* 执行转账 */ }
}
} else {
synchronized (to) {
synchronized (from) { /* 执行转账 */ }
}
}
避免在 synchronized 块内调用可能加锁的外部方法
比如在 `run()` 的同步块中调用 `someService.doSomething()`,而该方法内部又用了另一个锁——这极易引入不可控的锁依赖链。 建议:- 把同步范围缩到最小,只包裹真正共享的临界区代码
- 对外部服务调用移出 synchronized 块,或确认其线程安全性
- 如必须组合调用,提前梳理所有涉及的锁,并纳入统一顺序策略
优先使用 tryLock + 超时机制
相比 `synchronized`,`ReentrantLock.tryLock(long, TimeUnit)` 更可控,能主动退出争抢,避免无限等待。 示例(在自定义 `Thread` 子类中):private final ReentrantLock lock1 = new ReentrantLock();
private final ReentrantLock lock2 = new ReentrantLock();
public void run() {
boolean locked1 = false, locked2 = false;
try {
if (lock1.tryLock(100, TimeUnit.MILLISECONDS)) {
locked1 = true;
if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) {
locked2 = true;
// 执行业务逻辑
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
if (locked2) lock2.unlock();
if (locked1) lock1.unlock();
}
}
杜绝“持有锁时创建新线程并传递锁对象”
常见误区:在 `synchronized(obj)` 块中启动另一个 `Thread` 子类,并把 `obj` 传进去让它也去 `synchronized(obj)` ——表面看没问题,但若该子线程后续又尝试获取其他锁,就可能和当前线程形成交叉等待。 应做到:- 锁对象不跨线程随意暴露,尤其避免作为参数传给新线程
- 新线程如需访问共享状态,优先通过线程安全容器(如 `ConcurrentHashMap`)、消息队列或原子变量
- 必要时用 `ThreadLocal` 隔离线程私有状态,减少锁竞争
不复杂但容易忽略。

















