阿里面试:自旋锁是什么?谈谈底层实现原理?

阿里面试:自旋锁是什么?谈谈底层实现原理?-mikechen

大厂经常会自旋锁相关的问题,比如:什么是自旋锁?如何实现自旋锁?底层原理?下面全面详解自旋锁@mikechen

自旋锁

自旋锁:是一种轻量级锁,线程在获取不到锁时不会阻塞,而是通过不断循环检查锁状态(自旋),直到成功获取锁。

线程在等待锁释放期间,不会放弃CPU执行权,而是不断地循环检查锁的状态。

适用于:短时间持有锁的场景,以减少线程上下文切换的开销。

 

自旋锁实现原理

自旋锁的核心思想是:让线程在等待锁的过程中“忙等待”,即不断地循环检查锁的状态,而不是立即进入阻塞状态。

自旋锁实现,可以基于 CAS(Compare-And-Swap) 和 CPU 指令级原子操作,通过不断轮询锁状态来尝试获取锁,而不进入阻塞。

CAS 是一种无锁同步机制,可以在多线程环境下保证变量的安全更新。

阿里面试:自旋锁是什么?谈谈底层实现原理?-mikechen

CAS(Compare-and-Swap,比较并交换)是一种原子操作,它在多线程并发环境中用于实现线程同步。

boolean compareAndSwap(int *V, int E, int N) {
    if (*V == E) { // 如果当前值等于期望值
        *V = N;    // 则更新为新值
        return true; // 返回成功
    } 
    return false; // 否则更新失败
}

CAS 操作包含三个值:

V(当前值);

E(期望值);

N(新值);

只有当 V == E 时,才会将 V 更新为 N,否则更新失败,并重新尝试(自旋)。

CAS操作的核心思想是:

比较:

将内存中的一个值与预期值进行比较。

交换:

如果内存中的值与预期值相等,则将内存中的值更新为新的值。

如果内存中的值与预期值不相等,则不进行任何操作。

如下所示:

import java.util.concurrent.atomic.AtomicReference;

public class SpinLock {
    private AtomicReference<Thread> owner = new AtomicReference<>();

    public void lock() {
        Thread currentThread = Thread.currentThread();
        while (!owner.compareAndSet(null, currentThread)) {
            // 自旋等待
        }
    }

    public void unlock() {
        Thread currentThread = Thread.currentThread();
        owner.compareAndSet(currentThread, null);
    }
}

首先,尝试获取锁。

如果锁未被占用,则当前线程成功获取锁。

如果锁已被其他线程占用,进入自旋(不断尝试)。

其次,自旋等待。

线程不断尝试获取锁,而不会进入阻塞状态(即不会触发线程切换)。

如果锁很快释放,线程可以立即获取到锁,避免线程上下文切换的开销。

其次,成功获取锁后执行任务。

线程获取锁后,进入临界区,执行临界资源操作。

最后,释放锁。

任务完成后,线程使用 CAS 操作 释放锁,使其他线程可以获取锁。

自旋锁某些情况下效率很高,对于锁持有时间短的场景,自旋锁可以显著提高性能,因为它避免了线程阻塞、和唤醒的开销。

但是,如果锁的持有时间过长,自旋会导致线程长时间占用CPU,造成资源浪费。

评论交流
    说说你的看法