返回

CLH锁:理解等待队列和争用公平性的实现

后端

导论

在并发编程中,锁是一种至关重要的同步机制,用于协调对共享资源的访问,防止出现数据竞争和不一致的情况。CLH锁(Craig, Landin and Hagersten Lock)是一种具有争用公平性的计算机锁,意味着等待时间最长的线程将首先获得锁。

CLH锁的原理

CLH锁的核心思想是使用等待队列来管理对锁的请求。每个线程在请求锁时,都会被添加到等待队列的末尾。当锁可用时,等待队列中的第一个线程将获得锁,并将其从队列中删除。

为了实现争用公平性,CLH锁使用了一个循环变量来跟踪当前持有锁的线程。当一个线程释放锁时,它会将循环变量更新为下一个等待队列中的线程。

CLH锁的实现

以下是一个CLH锁的简单实现:

class CLHLock {
private:
    atomic_bool locked;
    atomic<CLHLock*> next;

public:
    CLHLock() : locked(false), next(nullptr) {}

    void lock() {
        CLHLock* prev = nullptr;
        while (true) {
            if (!locked.exchange(true)) {
                return;
            }
            CLHLock* nextNode = new CLHLock();
            nextNode->next.store(prev);
            prev = nextNode;
        }
    }

    void unlock() {
        locked.store(false);
        CLHLock* nextNode = next.exchange(nullptr);
        if (nextNode != nullptr) {
            nextNode->lock();
        }
    }
};

CLH锁的性能分析

CLH锁的性能与MCS锁非常相似。在低竞争的情况下,CLH锁和MCS锁都具有很高的吞吐量和很低的延迟。但在高竞争的情况下,CLH锁的性能会略微优于MCS锁。这是因为CLH锁的等待队列是显式的,而MCS锁的等待队列是隐式的。显式的等待队列可以减少线程在等待锁时对其他线程的影响。

总结

CLH锁是一种争用公平的计算机锁,具有较高的吞吐量和较低的延迟。它适用于需要争用公平性的并发场景,例如读写锁或多读写锁。