原文首发于:https://www.amoshuang.com/archives/1875,欢迎点击阅读
代码层面的锁的优化有很多方法,但是在有些时候通过设置JVM参数可以改变锁的行为,在虚拟机层面对锁进行优化
1.自旋锁
在多线程的并发中,频繁挂起和回复线程的操作会为系统带来极大的压力。特别是当访问共享资源仅需要花费很小一段的CPU时间时,锁的等待可能只需要很短的时间,这段时间可能比线程从挂起到恢复的时间还要短。
因此,为了这段时间进行重量级的线程切换是不值得的。为此,JVM引入了自旋锁。自旋锁可以使线程在没有取得锁时不被挂起而是执行若干个空循环。如果若干个空循环之后,线程获得了锁则继续执行,如果仍然没有获取锁则被挂起。
JVM虚拟机提供了-XX:+UseSpinning参数来开启自旋锁,使用-XX:PreBlockSpin参数来设置自旋锁的等待次数。
使用自旋锁后,线程被挂起的几率相对减少,线程执行的连贯性相对加强。这对于锁竞争不是很激烈,锁占用时间短的并发程序有积极意义。
但是要注意:对于锁竞争激烈,单线程锁占用时间长的并发程序,自旋锁在结束自旋之后往往还是避免不了执行被挂起的操作。这不仅浪费了CPU时间,还浪费了系统资源。
2.锁消除
锁消除指的是在JVM即使编译时,通过运行少下文的扫描,去除不可能存在共享资源竞争的锁。通过锁消除,可以节省毫无意义的请求锁时间。
在Java开发中,开发人员可能会使用一些诸如StringBuffer的内置API。虽然它们有对应的非同步版本,但是开发人员可能在完全没有多线程竞争的场合下使用它。
在这样的情况下,这些工具类内部的同步方法就是完全没有必要的。JVM虚拟机可以在运行时基于逃逸分析技术,捕获这些不可能存在竞争却申请锁的代码块,并消除这些不必要的锁,从而提高系统性能。
比如如下代码:
public static String craeteStringBuffer(String s1, String s2)