关于CAS等原子操作:
在开始说无锁队列之前,我们需要知道一个很重要的技术就是CAS操作——Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作,X86下对应的是CMPXCHG 汇编指令。有了这个原子操作,我们就可以用其来实现各种无锁(lock free)的数据结构。
这个操作用C语言来描述就是下面这个样子:
看一看内存*reg里的值是不是oldval,如果是的话,则对其赋值newval。
int compare_and_swap (int* reg, int oldval, int newval)
{
int old_reg_val = *reg;
if (old_reg_val == oldval)
*reg = newval;
return old_reg_val;
}
这个操作可以变种为返回bool值的形式(返回 bool值的好处在于,可以调用者知道有没有更新成功):
bool compare_and_swap (int *accum, int *dest, int newval)
{
if ( *accum == *dest )
{
*dest = newval;
return true;
}
return false;
}
#ifndef MUDUO_BASE_ATOMIC_H #define MUDUO_BASE_ATOMIC_H #include <boost/noncopyable.hpp> #include <stdint.h> namespace muduo { namespace detail { template<typename T> class AtomicIntegerT : boost::noncopyable { public: AtomicIntegerT() : value_(0) { } // uncomment if you need copying and assignment // // AtomicIntegerT(const AtomicIntegerT& that) // : value_(that.get()) // {} // // AtomicIntegerT& operator=(const AtomicIntegerT& that) // { // getAndSet(that.get()); // return *this; // } T get() { return __sync_val_compare_and_swap(&value_, 0, 0); //如果ptr所指向的内存中的数据等于oldval,则设置其为newval, 返回true。 } T getAndAdd(T x) { return __sync_fetch_and_add(&value_, x); // 返回值为*value_, value_的值变为value_ + x. } T addAndGet(T x) { return getAndAdd(x) + x; } T incrementAndGet() { return addAndGet(1); } T decrementAndGet() { return addAndGet(-1); } void add(T x) { getAndAdd(x); } void increment() { incrementAndGet(); } void decrement() { decrementAndGet(); } T getAndSet(T newValue) { return __sync_lock_test_and_set(&value_, newValue); // 将*ptr设为value并返回*ptr操作之前的值。 } private: volatile T value_; }; } typedef detail::AtomicIntegerT<int32_t> AtomicInt32; typedef detail::AtomicIntegerT<int64_t> AtomicInt64; } #endif // MUDUO_BASE_ATOMIC_H</span>