c++中的cas

169 阅读1分钟

CAS(Compare-And-Swap,比较并交换)是一种用于实现并发原子操作的技术,常用于多线程环境中的同步和锁-free 数据结构的实现。在C++中,CAS通常由std::atomic类的成员函数compare_exchange_weak()compare_exchange_strong()来实现。

这两个函数都用于比较std::atomic对象的当前值与期望值,并在它们相等时将新值存储到对象中。这个操作是原子的,因此可以在多线程环境中安全地使用。区别在于:

  • compare_exchange_weak():对于某些平台,如果在操作期间发生竞争(即其他线程修改了该值),这个函数可能会失败,但不会通知你。因此,你需要在循环中反复调用该函数,直到成功为止。

  • compare_exchange_strong():与compare_exchange_weak()相比,如果在操作期间发生竞争,这个函数会返回false,通知你操作失败,而不是继续执行。通常情况下,推荐使用这个函数。

以下是一个简单示例,演示了如何使用CAS实现一个简单的自旋锁:

#include <iostream>
#include <atomic>
#include <thread>

class SpinLock {
private:
    std::atomic_flag flag = ATOMIC_FLAG_INIT;

public:
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire)) {}
    }

    void unlock() {
        flag.clear(std::memory_order_release);
    }
};

SpinLock spinLock;

void threadFunction(int id) {
    spinLock.lock();
    std::cout << "Thread " << id << " acquired the lock" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    std::cout << "Thread " << id << " releasing the lock" << std::endl;
    spinLock.unlock();
}

int main() {
    std::thread t1(threadFunction, 1);
    std::thread t2(threadFunction, 2);

    t1.join();
    t2.join();

    return 0;
}

在这个示例中,SpinLock类使用std::atomic_flag实现自旋锁。在lock()函数中,我们使用了test_and_set()函数来尝试获取锁,如果获取失败就会自旋等待。unlock()函数简单地清除了flag,释放锁。

CAS是一种强大的原子操作,可以用于实现许多并发算法和数据结构,如无锁队列、无锁栈等。