深入剖析 Java 线程的 BLOCKED 状态

深入剖析 Java 线程的 BLOCKED 状态

在 Java 并发编程中,准确理解线程的生命周期状态是排查死锁、性能瓶颈的前提。在 Java 线程的 6 种状态(NEW, , , , , )中, 状态往往是容易被误解的一个。

许多开发者凭直觉认为:“只要线程被阻塞了,就是 状态”。这是一种极其普遍的错误认知。本文将详细梳理线程进入 状态的确切场景,并辟谣常见的误区。

一、 何时进入 状态?

在 Java 官方文档中深入剖析 Java 线程的 BLOCKED 状态, 状态的定义非常明确:线程正在等待获取一个内置的监视器锁以进入同步块/方法,或者在被 .wait() 唤醒后重新竞争锁失败时,线程处于此状态。

可以看出, 状态是 关键字的专属状态。具体触发场景有两个:

场景一:首次竞争内置锁失败

这是最常见的场景。当线程 A 已经持有了对象 obj 的监视器锁,正在执行 (obj) 代码块内部的代码。此时,线程 B 也尝试进入该同步块,由于锁被 A 占用java锁类型,线程 B 就会进入 状态,直到线程 A 释放锁。

场景二:被 wait() 唤醒后重入锁失败

这个场景经常被忽略,但在之前的讨论中我们已经明确它是真实的。

线程 A 在 代码块内部调用了 obj.wait()深入剖析 Java 线程的 BLOCKED 状态,此时线程 A 会释放锁,并进入 状态。随后,线程 B 获取到了锁,并调用了 obj.() 唤醒了线程 A。线程 A 被唤醒后,需要重新获取 obj 的锁才能从 wait() 方法返回并继续往下执行。如果此时线程 B 还没有执行完同步代码块(即尚未释放锁),线程 A 就会因为抢不到锁而进入 状态。二、 常见的四大误区

了解了触发场景后,我们来看看关于 状态最常见的四个误区。

误区一:等待 JUC 锁(如 )是 状态

事实:等待 等高级锁时,线程状态是 (或 ),而不是 。

这是面试和实际开发中最容易踩的坑。许多开发者认为“等锁”就是 ,但这仅适用于 。

为什么?

误区二:网络/磁盘 I/O 阻塞是 状态

事实:线程因为阻塞式 I/O(如 .read())而卡住时,其状态依然是 。

为什么?

在 Java 层面java锁类型, 状态不仅仅指“正在 CPU 上执行”,还包括“正在等待操作系统分配 CPU 时间片”以及“正在等待底层 I/O 资源”。

当线程执行阻塞式网络请求时,Java 虚拟机并不会将其标记为 。因为在 JVM 看来,线程并没有等待 Java 层面的锁,它只是把控制权交给了操作系统去等待网络数据。所以,当你用 查看一个卡在网络读取的线程时,你会看到它依然是 (通常伴随

.. 的堆栈)。

误区三:调用 .sleep() 会让线程进入 状态

事实:.sleep() 会让线程进入 状态。

为什么?

状态的唯一诱因是“等待 内置锁”。.sleep() 只是让当前线程主动让出 CPU 执行权,休眠一段时间,它与锁的竞争毫无关系。带时间的休眠属于 (限期等待)。

误区四:调用 .wait() 会进入 状态

事实:调用 .wait() 会进入 状态(或 )。

为什么?

虽然 wait() 必须在 块中调用,但线程一旦执行到 wait(),它就会立即释放持有的内置锁,并进入等待队列。既然锁被释放了,它就不存在“等待获取锁”的情况,因此绝对不是 。只有当它被 () 叫醒,重新去抢锁且抢不到的那一瞬间,才是 。

三、 总结与验证

为了方便记忆,我们可以用一个简单的公式来概括 Java 线程状态与锁/阻塞的关系:

你可以通过下面这段简单的代码,使用 或 IDEA 调试器亲自验证 JUC 锁的状态:

public class LockStateTest {
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        // 线程1:获取锁后一直休眠,不释放锁
        new Thread(() -> {
            lock.lock();
            try { Thread.sleep(1000000); } catch (Exception e) {}
        }, "Thread-Hold-Lock").start();
        try { Thread.sleep(100); } catch (Exception e) {}
        // 线程2:尝试获取锁,必然失败并被阻塞
        new Thread(() -> {
            lock.lock();
            try {} finally { lock.unlock(); }
        }, "Thread-Wait-Lock").start();
    }
}

运行上述代码java锁类型,通过 抓取线程堆栈,你会发现 -Wait-Lock 的状态是:

java.lang..State: (),而不是 。

准确区分这些状态,在排查线上“线程假死”或“死锁”问题时能起到决定性作用,避免南辕北辙。

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » 深入剖析 Java 线程的 BLOCKED 状态

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们