LockSupport 源码阅读

简介:

在java中,要让线程等待最普通的方法是调用Object.wait()方法,

Causes the current thread to wait until another thread invokes the notify() method for this object.

但是当我阅读JUC(java.util.concurrent)的源码时发现这个包不是这样做的, 我跟踪CountDownLatch.await()调用,最后跟到了LockSupport.park()方法里, 这里调用的是 unsafe.park()方法来block线程。

LockSupport 和 CAS一样是JUC很多控制机制的基础(但他们的底层其实都是在依赖Unsafe),下面就来学习下LockSupport这个类:


// Hotspot implementation via intrinsics API
private static final Unsafe unsafe = Unsafe.getUnsafe(); //unsafe 用来实现底层操作
private static final long parkBlockerOffset; //辅助参数,配合unsafe用的

//This object is recorded while
// the thread is blocked to permit monitoring and diagnostic tools to
// identify the reasons that threads are blocked.
//设置一个线程和关联的blocker对象,blocker用来做分析,debug用的
private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn’t need a write barrier here.
unsafe.putObject(t, parkBlockerOffset, arg);
}

//block当前线程,是否真的block了取决于permit是否available
//permit相当于1,0的开关, 默认是0, 调一次unpark就+1变成1了,调一次park会消费这个1又变成0了(park立即返回),
//再次调用park会变成block(因为没有1可以拿了,会等在这,直到有1),这时调用unpark会把1给回去(线程解锁返回)
//每个线程都有个相关的permit, permit最多一个,调用unpark多次也不会积累
//当为permit available时,方法会立即返回,不会block,反之就会block当前线程直到下面3件事发生
//1. 其他线程调用了unpark(此线程)
//2. 其他线程interrupts了此线程
//3. The call spuriously (that is, for no reason) returns.
public static void park() {
unsafe.park(false, 0L);
}

//对于给定线程,让permit变得avaliable,
public static void unpark(Thread thread) {
if (thread != null)
unsafe.unpark(thread);
}

//然后park有2个带限定时间的版本,所以一共有3个park version, 这3个version又有带blocker的debug版本
public static void parkNanos(long nanos) {
public static void parkUntil(long deadline) {

下面写些代码试下


System.out.println("start");
LockSupport.parkNanos(1000000000);
System.out.println("end");
//一开始会block线程,直到给定时间过去后才往下走

System.out.println(“start”);
LockSupport.unpark(Thread.currentThread());
LockSupport.parkNanos(1000000000);
System.out.println(“end”);
//不会block,因为一开始给了一个permit

System.out.println(“start”);
LockSupport.unpark(Thread.currentThread());
LockSupport.unpark(Thread.currentThread());
LockSupport.parkNanos(1000000000);
System.out.println(“inter”);
LockSupport.parkNanos(1000000000);
System.out.println(“end”);
//第一个park不会block,第2个会,因为permit不会因为多次调用unpark就积累

相关文章
|
SQL
判断MS SQLSERVER临时表是否存在
drop table  #tempcitys select * into #tempcitys from hy_citys 上面的语句第一次运行的时候就肯定出错了,但第二次就不会。 因为select * into #tempcitys from hy_citys自动创建了临时表#tempcitys ,第一次临时表不存在,drop table自然就出错了。
873 0
|
10天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
8天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
388 130
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
2天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
197 138
|
9天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
374 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
2天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
194 136
|
21天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1344 8
|
7天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。