synchronized
保证一段代码的执行是原子性的,同时只能被一个线程执行
非公平锁,不会按照等待锁的顺序让线程获得锁
锁的升级过程
偏向锁
为什么会出现偏向锁?用到synchronized的地方,大部分情况下都是单线程在使用,为了提高效率,在当做锁的Object对象的对象头里面记录下当前线程的线程id; 表示占用锁
轻量锁 (自旋锁)
自适应自旋锁
自旋锁,线程是活跃的,消耗cpu
自适应自旋,在轻量级锁中,我们用到了自适应。自适应的理解,是建立在锁的持有和释放能够很快完成,那么等待加锁的线程根据获取锁的时间,来自己调整自旋的次数,这样就避免了盲目等待,比如说,B线程发现A线程持有的锁很快就被释放了,那么就让自己多等待一会,否则就不等了
重量级锁
不自旋,线程进入等待状态
重量级锁,上面我们说到,重量级锁很耗费性能,为什么?原因是拿不到锁的线程,直接被park(挂起),然后放在等待队列里,等候被唤醒。所以这里就牵扯到了线程的切换,而线程的切换势必会在操作系统层面,进行内核和用户态的切换,这种切换肯定是耗费性能的。
一些问题。。
自旋锁一定比重量锁效率高吗?
不是,如果锁的竞争度过高,就是等待锁的线程数量过多,或者临界区(锁住的代码块)的执行时间过长,都不适合自旋,大量的线程活跃占用cpu资源,这个时候适合重量级锁,让线程等待
反之如果线程数量少,临界区执行时间短,适合自旋锁自旋锁什么时候升级为重量级锁?
jdk1.6之前有两种策略
1、自旋超过10次
2、自旋线程数超过cpu核数的一半
jdk1.6之后加入了自适应自旋,jvm优化了自己控制偏向锁打开是否一定会提示效率?为什么?
不一定,当业务场景明确一定会有多个线程来竞争锁,这个时候没必要打开偏向锁,多个线程来竞争偏向锁会有锁撤销的过程效率反而会降低
jvm启动默认4秒之后打开偏向锁