synchronized是基于Monitor来实现同步的。

Monitor 的工作机理:

  1. 线程进入同步方法中。
  2. 为了继续执行临界区代码,线程必须获取 Monitor 锁。如果获取锁成功,将成为该监视者对象的拥有者。任一时刻内,监视者对象只属于一个活动线程(The Owner)
  3. 拥有监视者对象的线程可以调用 wait() 进入等待集合(Wait Set),同时释放监视锁,进入等待状态。
  4. 其他线程调用 notify() / notifyAll() 接口唤醒等待集合中的线程,这些等待的线程需要重新获取监视锁后才能执行 wait() 之后的代码。
  5. 同步方法执行完毕了,线程退出临界区,并释放监视锁。

synchronized具体实现

同步方法使用ACC_SYNCHRONIZED标记符隐式的实现。

同步代码块采用monitorenter、monitorexit指令显式的实现。

ACC_SYNCHRONIZED

方法级别的同步是隐式的,它实现在方法调用和返回操作之中。虚拟机可以从方法常量池中的方法表结构(method_info structure)中的 ACC_SYNCHRONIZED 访问标志区分一个方法是否是同步方法。当调用方法时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否设置,如果设置了,执行线程先持有同步锁,然后执行方法,最后在方法完成时释放锁。

monitorenter

每一个对象都有一个monitor,一个monitor只能被一个线程拥有。当一个线程执行到monitorenter指令时会尝试获取相应对象的monitor,获取规则如下:

  • 如果monitor的进入数为0,则该线程可以进入monitor,并将monitor进入数设置为1,该线程即为monitor的拥有者。
  • 如果当前线程已经拥有该monitor,只是重新进入,则进入monitor的进入数加1,所以synchronized关键字实现的锁是可重入的锁。
  • 如果monitor已被其他线程拥有,则当前线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor。

monitorexit

只有拥有相应对象的monitor的线程才能执行monitorexit指令。每执行一次该指令monitor进入数减1,当进入数为0时当前线程释放monitor,此时其他阻塞的线程将可以尝试获取该monitor。

最新文章

  1. Design2:数据层次结构建模之二
  2. C++_STL
  3. bootstrap-fileupload-上传文件控件
  4. 利用 ffmpeg + ImageMagick + 批处理 生成高品质gif动画
  5. ORACLE 总结
  6. IOKit找不到问题定义
  7. bullet HashMap 内存紧密的哈希表
  8. 『软件介绍』SQLServer2008 基本操作
  9. 小米路由器mini如何设置外网访问wan网站的方法
  10. linux加入windows域之完美方案(转载)
  11. Java异常类(Throwable)
  12. hbase完全分布式安装
  13. Angular: 执行ng lint后如何快速修改错误
  14. PAT 乙级 1086 就不告诉你 (15 分)
  15. Maven install报MojoFailureException
  16. Memory Translation and Segmentation.内存地址转换与分段
  17. DLL接口的实现(虚函数)
  18. angular ui.router 路由传参数
  19. STM32 HAL库学习系列第2篇 GPIO配置
  20. ajax实现json循环输出结果

热门文章

  1. awk经常使用字符串处理函数
  2. Python 连接 Oracle数据库
  3. matplotlib绘制柱状图
  4. HMM、MEMM、CRF模型比较和标注偏置问题(Label Bias Problem)
  5. NGUI混合FingerGesture《卷二》分离触摸事件
  6. ASP.NET Core EF 查询获取导航属性值,使用Include封装
  7. Swap交换分区--continue
  8. [转]将Eclipse设置为黑色主题 方式一
  9. 一键安装lnmp-php(5)
  10. feather mac 问题小结