Java JDK1.6对Synchronized锁优化引入锁膨胀、锁消除、锁粗化、自旋锁、偏向锁、轻量级锁、重量级锁详解

本文详细介绍了Java JDK1.6中synchronized锁的优化,包括锁膨胀、锁消除、锁粗化、自旋锁、偏向锁、轻量级锁和重量级锁的工作原理和执行步骤,旨在理解JVM如何提高多线程环境下的性能。
摘要由CSDN通过智能技术生成

monitor原理及执行步骤

因为每个对象头中都存在monitor锁对象,所以java中可以用对象加锁。

对象结构大概分为对象头、实例变量和填充字节。

  • 对象头
    • Mark Word(标记字段):存储对象的hashCode、锁信息或分代年龄或GC标志等信息
    • Klass Pointer(类型指针):对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
    • 数组长度:只有数组对象保存了这部分数据。该数据在32位和64位JVM中长度都是32bit。
  • 实例变量:实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
  • 填充字节:第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

每一个锁都对应一个monitor对象,在HotSpot虚拟机中它是由ObjectMonitor实现的(C++实现)。每个对象都存在着一个monitor与之关联,对象与其monitor之间的关系有存在多种实现方式,查看部分ObjectMonitor.cpp源码:

ObjectMonitor () {
	// 指向持有ObjectMonitor对象的线程地址。
	_owner = NULL;

	//  存放调用wait方法,而进入等待状态的线程的队列。
	_WaitSet = NULL

	// 这里是等待锁block状态的线程的队列。
	_EntryList = NULL;

	// 锁的重入次数。
	_recursions = 0;

	// 线程获取锁的次数。
	_count = 0;
}

执行步骤:

  1. 当多个线程同时访问时,这些线程先被放进**_EntryList队列**中,线程处于blocked状态。
  2. 当其中的一个线程获取到对象的monitor后,该线程进入running状态,_owner指向当前线程,_count加1表示锁被一个线程获取到。
  3. 当running状态线程调用wait()方法,释放当前线程的monitor对,并进入waiting状态。_owner变为NULL,_count减1,将线程加入都_WaitSet队列中,当有线程notify()该线程时,将该线程加入到_EntryList队列中参与锁的竞争
  4. 当线程执行完成时,释放monitor对象,_owner为NULL,_count减1

锁的四种状态(无锁状态、偏向锁、轻量级锁、重量级锁)

JDK6之前只有两个状态:无锁、有锁(重量级锁),而在JDK6之后对synchronized进行了优化,新增了两种状态,总共就是四个状态:无锁状态、偏向锁、轻量级锁、重量级锁。

锁膨胀</

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值