synchronized的实现原理与应用
????????在多线程并发中synchronized一直存在,很多人把它称为重量级锁,但随着JavaSE1.6对sycnhronized进行了各种优化后,有些情况就不再那么重了。
接下来详解一下JavaSE 1.6为了减少获得锁和释放锁带来的性能消耗并引入了偏向锁和轻量级锁,以及锁的存储结构和升级过程
利用synchronized实现同步的基础:Java中每一个对象都可以作为锁。
具体表现:
- 对于同步方法:锁是当前的对象。
- 对于静态同步方法:锁是当前类的Class对象
- 对于同步代码块:锁是Synchonized括号里配置的对象
当一个线程视图访问同步代码块时,它首先必须先得到锁。退出或抛出异常时必须释放锁。
那么锁在哪里,锁里有哪些存储信息呢?
????????在JVM规范中,可以看到Synchonized在JVM的实现原理,JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,但二者的实现细节不一样。
????????代码块同步是使用monitorenter和monitorexit指令实现的,而方法同步是使用另外一种方式实现,细节jvm并没有详细说明。但是方法的同步同样也可以实现者两个指令
- monitorenter指令是在编译后插入到同步代码块的开始位置
- monitorexit是插入到方法结束处和异常处
????????jvm要保证每个monitorenter必须有对应的monitorexit与之匹配,任何对象都有一个monitor与之关联。当一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁。
Java对象头
synchronized用的锁是存在Java对象头里的。(32位机,一字宽等于4字节)
- 如果对象是数组类型,则虚拟机用三个字宽(Word)存储对象头,
- 如果对象是非数组类型,则用两个字宽存储对象头
Java对象头里的Mark Word里默认存储对象的HashCode、分代年龄和锁标记位。
32位JVM的Mark Word的默认存储结构如表2-3所示。
????????在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。Mark Word可能变化为存储以下4种数据,如表2-4所示。
?
锁的升级和对比
Java SE1.6 减少获得锁和释放锁带来的性能消耗,引入了偏向锁🔒和轻量级锁🔒。
在Java SE 1.6中,锁一共有四种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。
这几个状态会随着竞争情况逐渐升级,锁可以升级但不能降级,目的是:为了提高获得锁和释放锁的效率。
下一篇文章 =》偏向锁
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!