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