muduo库源码分析之 Atomic.h

首先在分析这个类之前了解一下原子操作的概念,原子操作(atomic operation)指的是由多步操作组成的一个操作。如果该操作不能原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集。

任何要求多于一个函数调用的操作都不是原子操作,因为在两个函数调用之间,内核可能会临时挂起线程,执行其他的操作,当内核切换回当前线程时,之前的数据可能别修改,所以不能保证是原子操作。

在C++11之前,C++标准中并没有对原子操作进行规定。如果我们想要实现原子操作,就只能借助汇编语言,或者第三方的线程库(比如pthread来实现)。

在C++11中,终于有了原子操作的概念。标准提供了多个原子操作数据类型,atomic_int、 atomic_long等。在程序中使用这些数据类型的时候,编译器将保证针对原子数据类型的操作都是原子性的。也就是说,编译器保证多个线程访问这个共享资源的正确性。这样,我们在程序中就可以较少锁的使用,提高程序效率。

muduo库中同样封装了相同功能的Atomic类,接下来我们详细的分析这个类的实现方式

template//首先这个类是一个模板类,接受一个类型参数
class AtomicIntegerT : noncopyable//表示这个类不能后拷贝和赋值
{
 public:
  AtomicIntegerT()
    : value_(0)
  {
  }

  

  T get()
  {
    // in gcc >= 4.7: __atomic_load_n(&value_, __ATOMIC_SEQ_CST)
    return __sync_val_compare_and_swap(&value_, 0, 0);
  }

  T getAndAdd(T x)
  {
    // in gcc >= 4.7: __atomic_fetch_add(&value_, x, __ATOMIC_SEQ_CST)
    return __sync_fetch_and_add(&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)
  {
    // in gcc >= 4.7: __atomic_exchange_n(&value, newValue, __ATOMIC_SEQ_CST)
    return __sync_lock_test_and_set(&value_, newValue);
  }

 private:
  volatile T value_; //只有唯一的成员函数,是一个volatile修饰的T类型,
};
}  // namespace detail

typedef detail::AtomicIntegerT AtomicInt32;
typedef detail::AtomicIntegerT AtomicInt64;

在下面和大家介绍一下GCC 提供的原子操作-:__sync_fetch_and_add系列

_sync_fetch_and_add系列一共有十二个函数,有加/减/与/或/异或/等函数的原子性操作函数,__sync_fetch_and_add,顾名思义,先fetch,然后自加,返回的是自加以前的值。以count = 4为例,调用__sync_fetch_and_add(&count,1),之后,返回值是4,然后,count变成了5.
    有__sync_fetch_and_add,自然也就有__sync_add_and_fetch,呵呵这个的意思就很清楚了,先自加,在返回。他们哥俩的关系与i++和++i的关系是一样的。被谭浩强他老人家收过保护费的都会清楚了。
    有了这个宝贝函数,我们就有新的解决办法了。对于多线程对全局变量进行自加,我们就再也不用理线程锁了。下面这行代码,和上面被pthread_mutex保护的那行代码作用是一样的,而且也是线程安全的。
__sync_fetch_and_add( &global_int, 1 );
    下面是这群函数的全家福,大家看名字就知道是这些函数是干啥的了。
在用gcc编译的时候要加上选项 -march=i686
type __sync_fetch_and_add (type *ptr, type value);
type __sync_fetch_and_sub (type *ptr, type value);
type __sync_fetch_and_or (type *ptr, type value);
type __sync_fetch_and_and (type *ptr, type value);
type __sync_fetch_and_xor (type *ptr, type value);
type __sync_fetch_and_nand (type *ptr, type value);
type __sync_add_and_fetch (type *ptr, type value);
type __sync_sub_and_fetch (type *ptr, type value);
type __sync_or_and_fetch (type *ptr, type value);
type __sync_and_and_fetch (type *ptr, type value);
type __sync_xor_and_fetch (type *ptr, type value);
type __sync_nand_and_fetch (type *ptr, type value)

你可能感兴趣的:(muduo源码分析,C++,Linux,muduo)