JUC的Lock和build-in的synchronized是如何实现的

本文深入探讨了Java并发库(JUC)中的Lock机制与内置synchronized关键字的实现原理。Lock通过标记位和LockSupport实现线程的阻塞与唤醒,利用Unsafe类的CAS方法确保线程安全。synchronized则是基于每个对象的监视器实现,包含计数、持有者信息和等待队列,由JVM指令如monitorenter和monitorexit控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JUC的Lock和build-in的synchronized是如何实现的

补充JUC的Lock是如何实现的

通过Lock对象的一个int标记位(名为state),记录此lock占用的线程数。如果为0表示此lock无占用,则不阻塞,如果>0则表示暂用,需要阻塞。

阻塞使用和释放阻塞使用LockSupport的park/unpark来实现,其调用更底层的native方法来实现。

Lock中大量使用了Unsafe类的CAS方法来保证线程安全,CAS就是比较并替换,例如在修改这个state的时候,使用的是CAS方式。传入预期的值,如果修改过程被其他线程改了,则修改失败。

CAS通过一些更加底层的指令来实现,例如汇编指令cmpxchg,这个指令将比较并改变两个动作绑在一起,成为一个原子操作。原子操作就是说不可再分割,这两个动作(比较、改值)要么一起执行,要么一起放弃。

synchronized是如何实现的

每个Object对象都可以成为锁,因为每个Object都有一个监视器(monitor),这就是任何Object对象都可以作为锁的原因。

我们通常说Object是锁,更准确可能是Object的监视器才是锁。

monitor里有标记(count),0就表示当前没线程,1表示有,>1表示重入了。

monitor不光维护锁引用数,还有WaitSet等,这就是调用wait后记录哪些线程在该监视器的队列上。

至于怎么线程休眠、唤醒,这是JVM、操作系统和CPU底层的一些技术,例如JVM提供了一些指令,当然JVM的指令最终是操作系统和CPU的指令的一个封装。比如对于synchronized(lock),对其反编译,会看到monitorenter和monitorexit,这就是JVM提供的指令(通常monitorexit有两个,因为另一个是异常是保证释放的),而synchronized方法,会生成一个ACC_SYNCHRONIZED标记,这就让运行到该方法时,判断当前monitor的count是否为0。

monitor的实现是在C++中的
iamge
其中

  • _count:就是标识线程有多少线程占用(0,无,1-有,>1重入)
  • _owner:记录持有锁的线程,不持有的时候变成null
  • _WaitSet:调用wait的时候,线程就是进入这个等待队列里的

资料参考

比较浅显

深度文章,涉及自旋锁等,讲述了Lock和synchronized的实现原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值