1,总介绍如下:
2,解说:
(1)无锁态(刚刚new出来的对象):
无锁态,也就是说的,这个对象的刚刚创建出来,没有被加锁
(2)偏向锁(一个线程上锁):
类似一个线程的CAS, 当线程并不激烈的时候的,只需要记录上当前的线程指针,执行到当前记录当前的线程锁,直接执行。
(3)轻量级锁(多个线程竞争,但是竞争不激烈):
synchronize默认 轻量级锁又称为,自旋锁,无锁: 竞争的线程每一个都生成Lock Record,作为版本号,看看是不是我修改的线程,如果是,进入资源修改资源,如果不是,那么就不断请求的循环,因此叫做自旋锁。 自选次数(10次)过多的时候,就会大量消耗CPU资源,这个时候就会升级为重量级锁。
什么是自适应自旋锁?(JDK6之后默认开启)
人工调整自旋次数,自然也有交给JVM自己调整的。 JVM自己调整自旋次数,称为:自适应自旋锁。
(4)重量级的锁(操作系统用户态->内核态;产生消息系列):
在之前的三种锁中,都是处于用户态的锁,效率比较高; 重量级锁则是向CPU申请一把重量级锁(重量级锁在CPU中是有限的),处于内核态运行 那么为什么要升级到重量级的锁呢? 因为不断自旋(循环请求)对于CEO符合太大了,所以升级为重量级锁。 重量级锁,形成一个消息队列,没有得到请求线程,会处于阻塞状态。
3,锁消除:
当没有竞争的时候,也就说,有锁没锁一样就会产生锁消除。 一般用于局部变量,线程私有,当线程私有资源不可能共享,那么就会锁消除
public void add(String str1,String str2)
{
StringBuffer buffer=new StringBuffer();
buffer.append("1234").append("sjdjasdhj");
}
就像是buffer变量, 虽然对append()使用了synchronize ,但是buffer变量根本没有可能的共享,他是线程私有。 锁消除
4,锁粗化:
public String test(String str1)
{
int i=0;
StringBuffer sb=new StringBuffer();
while (i<100)
{
sb.append(str1);
i++;
}
return sb.toString();
}
我们知道StringBuffer是线程安全,append()方法加了synchronize
如果按照上述代码的逻辑,那么就会加100次锁,但是没有必要,所以JVM对此进行优化,对while循环进行加锁,这样只需要加一次
5,锁消除(不重要)
锁消除过程的,发生在GC上面,所以老文认为不重要的了。
|