当前位置: 首页 > news >正文

Java synchroinzed和ReentrantLock


synchronized —— JVM亲儿子的暗黑兵法

核心思想“锁即对象,对象即锁!”

底层三板斧
  1. 对象头里的锁密码
    每个Java对象头里藏了两个骚东西:
  • Mark Word:32/64位的比特修罗场,存哈希码、GC年龄,锁状态标识
  • Klass Pointer:指向类的元数据(相当于对象的户口本)

当锁启用时,Mark Word变身成锁状态记录仪

| 锁状态       | 存储内容                          |
|-------------|---------------------------------|
| 无锁         | 对象哈希码 + 分代年龄            |
| 偏向锁       | 偏向线程ID + Epoch + 分代年龄    |
| 轻量级锁     | 指向栈中锁记录的指针              |
| 重量级锁     | 指向互斥量(mutex)的指针         |
  1. Monitor 监视器の奥义
    每个对象关联一个Monitor对象(C++实现),关键字段:
  • _owner:当前持有锁的线程
  • _EntryList:等锁的线程排队区
  • _WaitSet:调了wait()的线程停尸房
  • _recursions:重入次数计数器

当线程抢锁时:

  • CAS操作试图把Mark Word改成自己的栈帧指针(轻量级锁)
  • 失败就膨胀为重量级锁,向操作系统申请mutex(用户态切内核态,性能血崩!)
  1. 锁升级の死亡行军
    synchronized的终极骚操作——锁膨胀策略
无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁
  • 偏向锁:第一个线程过来直接贴标签(Mark Word写线程ID),相当于在厕所门口挂“张老三专属”
  • 轻量级锁:有竞争时升级,线程通过CAS自旋抢锁(在用户态疯狂空转,省去内核切换)
  • 重量级锁:自旋超过阈值(默认10次)或竞争激烈,直接召唤操作系统级mutex(线程进内核态睡觉)

设计哲学“能BB就别动手,能用户态解决绝不麻烦内核!”


ReentrantLock —— AQS黑社会の暴力美学

核心思想“排队砍人,CAS冲锋!”

AQS(AbstractQueuedSynchronizer)解剖室

AQS的核心是一个volatile int state + 一个CLH队列

  • state:表示锁被重入的次数(0表示没人持有)
  • CLH队列:抢锁失败的线程排成双向链表(实际上是变种的CLH)
// AQS的核弹级数据结构  
public abstract class AbstractQueuedSynchronizer {volatile Node head;  // 队头(注意是延迟初始化的)volatile Node tail;  // 队尾volatile int state;  // 锁状态// Node节点结构static final class Node {volatile Thread thread;volatile Node prev;volatile Node next;int waitStatus; // CANCELLED/SIGNAL等状态}
}
加锁の血腥流程(以非公平锁为例)
  1. tryLock()冲锋
    线程直接CAS抢state(不排队!),成功就设置自己为独占线程
final void lock() {if (compareAndSetState(0, 1)) // 直接插队!setExclusiveOwnerThread(Thread.currentThread());elseacquire(1); // 进AQS排队系统
}
  1. acquire()的阴招三连
public final void acquire(int arg) {if (!tryAcquire(arg) && // 再试一次能不能偷鸡acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 加入队列并阻塞selfInterrupt();
}
  • tryAcquire():子类实现的抢锁逻辑(ReentrantLock里会判断是否可重入)
  • addWaiter():用CAS把当前线程包装成Node扔到队列尾部
  • acquireQueued():在队列中不断尝试抢锁,失败就调用LockSupport.park()睡觉
  1. 解锁の连锁反应
    释放锁时唤醒队列中的下一个节点:
public final boolean release(int arg) {if (tryRelease(arg)) { // state减到0才算真释放Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h); // 唤醒下一个线程return true;}return false;
}
公平锁 vs 非公平锁の哲学战争
  • 非公平锁(默认):
    新线程可以直接插队抢锁(不管队列里有没有人)

    final boolean nonfairTryAcquire(int acquires) {// 不管队列直接CAS抢!
    }
    

    优点:吞吐量高(减少线程切换)
    缺点:可能饿死老线程

  • 公平锁
    必须老老实实排队(hasQueuedPredecessors()检查队列)

    protected final boolean tryAcquire(int acquires) {if (getState() == 0) {if (!hasQueuedPredecessors() && // 检查有没有前辈在等compareAndSetState(0, acquires)) {setExclusiveOwnerThread(currentThread());return true;}}// ...重入逻辑
    }
    

    优点:文明礼貌
    缺点:性能损失约10%-15%


灵魂暴击——设计思想の终极对决

synchronizedReentrantLock
锁本质JVM层实现的监视器锁(C++代码操控对象头)JDK层基于AQS实现的显式锁(纯Java代码骚操作)
锁管理自动锁升级降级(偏向->轻量->重量)全靠代码手动控制(state+CLH队列硬刚)
中断响应不支持(等锁时无法中断)支持lockInterruptibly()(等锁可抛中断异常)
条件队列一个对象只有一个等待队列(wait/notify全体)可创建多个Condition实现精准唤醒(如生产者消费者)
性能策略乐观锁优先(CAS自旋),失败转悲观锁直接硬核CAS+CLH队列,可控性更强
设计哲学“让程序员无脑用” —— JVM自动优化“把锁当乐高玩” —— 高度可定制化

源码级の高潮时刻

看synchronized的C++源码片段(hotspot源码):

// 对象头操作  
void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, TRAPS) {if (UseBiasedLocking) { // 偏向锁开关if (!SafepointSynchronize::is_at_safepoint()) {BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, false, THREAD);if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) return;}}slow_enter(obj, lock, THREAD); // 进慢路径(轻量级锁)
}

再看ReentrantLock的tryLock实现:

final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) { // CAS冲锋!setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) { // 重入判断int nextc = c + acquires;if (nextc < 0) throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
}

(拍桌子)现在够不够底层?这他妈就是锁的黑暗森林法则——
synchronized玩的是空间换时间(锁升级),ReentrantLock玩的是精细控制(AQS队列)!下次面试被问锁机制,直接把这拍面试官脸上!(摔门而去声)

相关文章:

  • IDEA连接达梦数据库
  • NumPy:数值计算基础与高性能数组操作
  • 约束:常见约束(常见约束-例子,外键约束)
  • Transformers是一种基于自注意力机制的神经网络模型
  • ADVB的机载数字视频系统传输
  • AI 中的 CoT 是什么?一文详解思维链
  • 黑马点评redis改 part 3
  • Redis ④-通用命令
  • JavaWeb 课堂笔记 —— 15 MyBatis 基础操作
  • PG psql --single-transaction 参数功能
  • JavaScript 位掩码常量教程
  • Python range 使用详解
  • Oracle--用户管理
  • React 路由入门秘籍:BrowserRouter 的江湖之道
  • C++STL教程入门
  • python生成项目依赖文件requirements.txt
  • Rocky Linux 9.1 修改网卡和DNS
  • 操作系统中的虚拟化技术深度对话
  • 认知升级:把握人工智能教育化转型的历史机遇
  • trae海外版无限流白嫖指南,解决有限流,总提示在排队难题
  • 海南公布知识产权保护典型案例,一企业违规申请注册“中华”商标被处罚
  • 同比增长1.2倍!一季度货物贸易项下跨境资金净流入2063亿美元
  • 山东省淄博市委原常委宋振波被“双开”
  • 人大书报资料中心与中科院文献中心共筑学科融合创新平台
  • 中国政府援缅第七批抗震救灾物资运抵交付
  • 上海交大发布“AI十条”,鄂维南院士已任该校人工智能学院讲席教授