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


    原子性操作可以做到比互斥锁更小的开销,在多线程编程中原子性操作是非常有用的。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);
      }
    }
    
    

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

  • 相关阅读:
    JS常见错误和分析
    angularjs 笔记(1) -- 引导
    各大浏览器hack
    AngularJS 配置和运行phonecat错误
    npm start 作用
    $.prop()和$.attr() 区别用法
    HDU 1251 统计难题 (Tire树)
    Luogu P3370 【模板】字符串哈希
    Luogu P3385 【模板】负环
    LuoguP1563 玩具谜题
  • 原文地址:https://www.cnblogs.com/sigma0-/p/12630489.html
Copyright © 2020-2023  润新知