一.synchronized锁的定义
synchronized是一个Java关键字,是jvm层级的,它是一种互斥锁,一次只能允许一个线程进入被锁住的代码块。如果synchronized修饰的是实例方法,对应的锁则是对象实例,如果synchronized修饰的是静态方法,对应的锁则是当前类的Class实例,锁住代码块的锁,可以是类的实例对象,或者是类的Class实例。
JVM中有线程共享的区域:java方法区和堆内存,堆内存中存的是实例化的对象,对象内存中除了存字段的信息外,还会有一个对象头:
根据上面的图片可以看到,对象头中的信息有:
1:class meta address,就是指向方法区内的,类的元信息。
2:array length,是当对象是数组对象时,记录数组的长度的。
3:mark word,记录的是锁的信息,即锁的状态、锁的类型等。
二.锁的状态
synchronized 在JDK1.6 之后做了一些优化,为了减少获得锁和释放锁来的性能开销,引入了偏向锁、轻量级锁、自旋锁、重量级锁,锁的状态根据竞争激烈的程度从低到高不断升级。
## 没有开启偏向锁测试:
1. 一个对象如果没有被任何线程当做锁去使用,就是无锁状态。 01
2. 一个对象如果被一个线程当做锁去使用,就是轻量级锁状态。 00
3.一个对象当做锁被一个线程持有,另外一个线程还继续去获取该锁,就是重量级锁。 10
偏向锁:
大部分情况下,锁不仅仅不存在多线程竞争,而是总是由同一个线程多次获得,
为了让线程获取锁的代价更低就引入了偏向锁的概念。
怎么理解偏向锁呢?当一个线程访问加了同步锁的代码块时,
会在对象头中存储当前线程的 ID,
后续这个线程进入和退出这段加了同步锁的代码块时,
不需要再次加锁和释放锁。
而是直接比较对象头里面是否存储了指向当前线程的偏向锁。
如果相等表示偏向锁是偏向于当前线程的,就不需要再尝试获得锁了。
修改偏向锁的延迟时间的参数:-XX:BiasedLockingStartupDelay=0
## 开启偏向锁测试:
1.一个对象没有被作为锁对象,处于无锁可偏向状态。(对象头中没有记录线程ID)101
2.一个对象被一个线程作为锁对象,处于轻量级锁状态。(对象头中记录了线程ID)101\
3.一个对象被一个线程作为锁对象,释放锁对象后(但是该线程没有消亡时),其他线 程再获取该锁对象,则处于轻量级锁状态。000
4.一个对象被一个线程作为锁对象,没有释放锁,其他线程也要获取该锁对象,就处 于重量级锁状态。010