muduo网络库源码学习————原子性操作Atomic.h

来源:互联网 发布:展示实时数据 时间轴 编辑:程序博客网 时间:2024/05/21 06:26

原子性操作可以做到比互斥锁更小的开销,在多线程编程中原子性操作是非常有用的。Atomic.h文件位于muduo/base下,代码如下:

// Use of this source code is governed by a BSD-style license// that can be found in the License file.//// Author: Shuo Chen (chenshuo at chenshuo dot com)//原子性操作:比锁的开销更小#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);//判断value的值是否为零,如果为0则赋值0    //返回的是未赋值之前的值,其实就是获取value的值  }  T getAndAdd(T x)  {//先获取然后执行加的操作,返回的是未修改的值    return __sync_fetch_and_add(&value_, x);  }  T addAndGet(T x)  {//先加然后获取    return getAndAdd(x) + x;//这里是调用getAndAdd函数,返回之后再加上x  }  T incrementAndGet()  {//自加1    return addAndGet(1);  }  T decrementAndGet()  {//自减1    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);  } private:  volatile T value_;//volatile关键字确保指令不会因编译器的优化而省略(防止编译器对代码进行优化)  //每次都从内存读取数据而不是使用保存在寄存器中的备份  //是为了避免其他线程已经将该值修改};}//两个实例化,32位和64位的原子性操作typedef detail::AtomicIntegerT<int32_t> AtomicInt32;typedef detail::AtomicIntegerT<int64_t> AtomicInt64;}#endif  // MUDUO_BASE_ATOMIC_H

其测试代码为Atomic_unittest.cc主要是进行一些简单的判别操作:

#include <muduo/base/Atomic.h>#include <assert.h>//原子性操作的测试函数int main(){  {//64位的原子性操作  muduo::AtomicInt64 a0;  //断言测试一个条件并可能使程序终止  assert(a0.get() == 0);//首先肯定会被置为0  assert(a0.getAndAdd(1) == 0);//加1,先获取然后加,还是0  assert(a0.get() == 1);//此时变为1  assert(a0.addAndGet(2) == 3);//先加然后获取,所以是3  assert(a0.get() == 3);  assert(a0.incrementAndGet() == 4);//先加然后获取  assert(a0.get() == 4);  a0.increment();  assert(a0.get() == 5);  assert(a0.addAndGet(-3) == 2);  assert(a0.getAndSet(100) == 2);  assert(a0.get() == 100);  }  {//32位的原子性操作  muduo::AtomicInt32 a1;  assert(a1.get() == 0);  assert(a1.getAndAdd(1) == 0);  assert(a1.get() == 1);  assert(a1.addAndGet(2) == 3);  assert(a1.get() == 3);  assert(a1.incrementAndGet() == 4);  assert(a1.get() == 4);  a1.increment();  assert(a1.get() == 5);  assert(a1.addAndGet(-3) == 2);  assert(a1.getAndSet(100) == 2);  assert(a1.get() == 100);  }}

单独编译后运行结果如下,因为断定都是正确的,所以执行不会有任何的结果
这里写图片描述

1 0
原创粉丝点击