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

有目标就不怕路远。年轻人.无论你现在身在何方.重要的是你将要向何处去。只有明确的目标才能助你成功。没有目标的航船.任何方向的风对他来说都是逆风。因此,再遥远的旅程,只要有目标.就不怕路远。没有目标,哪来的劲头?一车尔尼雷夫斯基

导读:本篇文章讲解 JUC的Lock和build-in的synchronized是如何实现的,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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的实现原理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/135325.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!