@yudesong
2018-02-12T03:05:32.000000Z
字数 1763
阅读 821
Java 锁
在多线程的加锁机制中,JVM会首先尝试乐观锁,失败后才调用悲观锁。
在HotSpot虚拟机中,对象在内存中的存储布局分为三部分:对象头、实例数据、对其填充。
对象自身的运行时数据
如:哈希吗(HashCode)、GC分代年龄(Generational GC Age)等,这部分数据的长度在32位和64位的虚拟机中分别为32bit和64bit,简称“Mark Word”
如果对象是数组类型,则虚拟机用3个Word(字宽)存储对象头,如果对象是非数组类型,则用2Word存储对象头。
指向方法区对象类型数据的指针,如果是数组对象的话,还会有一个额外的部分用于存储数组长度。
对象头信息是与对象自身定义的数据无关的额外存储成本。它会根据对象的状态复用自己的存储空间。例如:在32位的HotSpot虚拟机中对象未被锁定的状态下,Mark Word的32bit空间中的25bit用于存储对象哈希吗(HashCode),4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0
Java SE 1.6种锁一共有四种状态,级别从低到高:无锁状态、偏向锁、轻量级锁、重量级锁。随着竞争的情况逐渐升级,但不能降级。
* 偏向锁
顾名思义,就是偏向于当前已经占有锁的线程。如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。
-XX:+UseBiasedLocking
在JDK1.6中,Java虚拟机提供-XX:+UseSpinning参数来开启自旋锁,使用-XX:PreBlockSpin参数来设置自旋锁等待的次数。
在JDK1.7开始,自旋锁的参数被取消,虚拟机不再支持由用户配置自旋锁,自旋锁总是会执行,自旋锁次数也由虚拟机自动调整。
轻量级锁
重量级锁
锁粗化
这看起来与思路1有冲突,其实不然。思路1是针对一个线程中只有个别地方需要同步,所以把锁加在同步的语句上而不是更大的范围,减少线程持有锁的时间;
锁消除
锁消除是编译器做的事:根据代码逃逸技术,如果判断到一段代码中,堆上的数据不会逃逸出当前线程(即不会影响线程空间外的数据),那么可以认为这段代码是线程安全的,不必要加锁。
参考文献
1. https://www.cnblogs.com/charlesblc/p/5994162.html
2. https://www.jianshu.com/p/78cf35f01b2f
3. http://www.cnblogs.com/think-in-java/p/5520462.html
