锁的优化
高效并发是从 JDK1.5
到 JDK1.6
的一个重要改进,也提供了各种锁优化技术,这些技术的存在也会对锁的性能做了进一步的改善与提高。在面试的过程中并发编程方面的知识也是少不了这些的学习。
所以今天也算是来对所有的优化都做上一个总结。
注:此篇博文大部分内容出自《深入理解Java虚拟机》,一部分是本人在看个篇博文的个人理解。关于不知道如何获取电子版的朋友,微信读书上有完整版本,希望能帮到在学习这方面知识的小伙伴。
下面开始这些锁的介绍。
自旋锁与自适应自旋
在了解这两个优化技术之前首先了解在互斥操作时候会出现的情况–Java的线程是映射到操作系统的原生线程之上的,如果要阻塞或唤醒一个线程,都需要操作系统来帮忙完成,这就需要从用户态转换到核心态中,因此状态转换需要耗费很多的处理器时间。同时,虚拟机的开发团队也注意到了很多的应用上,共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得。
这里就引入了自旋锁:
自旋
在一个线程已经拥有了一个锁时候,此时若是有一个线程想要再来请求,就会让后面请求锁的线程“等待一下”,但是这个等待并不会放弃处理器的执行时间,看看持有锁的线程是否会很快的释放锁。我们只需要让这个线程执行一个忙循环(自旋)。就是所谓的自旋锁。
注意:对于自旋来说不能代替阻塞,对于自旋本身来说虽然能够避免了线程切换的开销,但是仍然要占用处理器的时间,所以要是等待时间较短效果还是比较好,但是等待时间长,就会白白浪费资源,而起不到任何的作用。所以这个自旋的次数要进行限制,但是这个次数是多少呢,引出了自适应自旋锁。
自适应自旋锁
对于自适应自旋锁来说,自旋的次数就不会再受到限制,而是根据同一个锁上的自旋时间以及锁的拥有者状态来决定。对于同一个锁对象上,自旋刚刚成功,并且持有锁的线程正在运行,此时虚拟机就会认为这次的自旋也会成功。若是对于某一个锁来说,自旋很少成功,那么在以后要获取这个锁时候