Java并发编程——自旋锁和自适应自旋锁

自旋锁(spinlock)

问题引入

当使用 synchronized 进行加锁后,对于多个线程竞争临界区代码时,若其中一个线程正在访问临界区,则其它线程都由于获取不到锁而被阻塞,直到原线程执行完毕,释放锁后,阻塞线程才能被唤醒,参与 CPU 调度

对于阻塞和唤醒操作,需要操作系统的介入,在内核态完成,系统开销较大,为了提高效率,减少资源浪费。引入自旋锁(spinlock)

核心思想

在多处理器的环境下,临界区被一个线程访问时,其它要访问临界区的线程不进入阻塞,而是进行自旋,循环等待一段时间,若在这期间原线程释放锁,则获取锁,若原线程一直不释放锁,当线程超过设置的自旋阈值后,则被阻塞

使用自旋锁的线程,自旋过程实际上是忙等待(busy-waiting)

若线程任务较为复杂,执行时间长,自旋不成功,反而白白浪费资源,降低效率

使用场景

任务不复杂的线程,线程状态切换的开销要大于任务执行的开销,可以使用自旋锁进行优化


自适应自旋锁

问题引入

自旋锁的阈值是人为设定的,过高过低都会一定程度影响效率,且阈值固定,也降低了灵活性,为了解决这一问题,在 Java 6 引入了自适应自旋锁

核心思想

自旋阈值不再人为设定,而是由上一次在同一个锁上的自旋时间和锁拥有者的状态决定的

若在同一个锁对象上,自旋成功过,且持有锁的线程正在运行,JVM 就认为自旋获取锁的可能性大,延长自旋时间

反之,若在同一个锁对象上,自旋很少成功或者没有成功过,JVM 就会减少自旋时间或者取消自旋

Guess you like

Origin blog.csdn.net/qq_25274377/article/details/120625273