muduo源码解析2-AtomicIntegerT类
AtomicIntegerT
template<typename T> class atomicTntergerT:public noncopyable { };
作用:
与std::aotmic<int> 类似,主要实现对 int32_t 和 int64_t 类型的原子操作。
在内部并不是使用互斥锁实现原子性,而是利用__sync_val_compare_and_swap和__sync_fetch_and_add在内部实现原子操作。
成员变量:
private: volatile T m_value;
volatile防止编译器对该变量进行优化,即直接在内存中进行存取,而不是优化到寄存器中进行存取,主要是为了防止变量的值在内存中和寄存器中不一致。
成员函数:
public: atomicTntergerT():m_value(0){} T get() { return __sync_val_compare_and_swap(&m_value,0,0); } T getAndAdd(T x) { return __sync_fetch_and_add(&m_value,x); } T addAndGet(T x) { return __sync_add_and_fetch(&m_value,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 x) { return __sync_lock_test_and_set(&m_value,x); }
大多是常见的运算操作,只不过在这里全部实现了多线程环境下的原子操作。
测试:
计算任务:THREAD_NUM个线程让count++ NUM次
测试mutex,atomic和atomicInt64的性能
测试结果
mutex 2198041
atomic 346589
atomicInt64 345607
std::atomic和atomicInt64表现差不多.都比互斥锁要好一点
测试代码:
#include<iostream> #include"base/timestamp.h" #include"base/atomic.h" #include<mutex> #include<atomic> #include<thread> using namespace mymuduo; #define NUM 200000 #define THREAD_NUM 100 std::mutex mutex; long long count1=0; std::atomic<int64_t> count2; atomicInt64 count3; void workerthread1() { for(int i=0;i<NUM;i++) { mutex.lock(); count1++; mutex.unlock(); } } void workerthread2() { for(int i=0;i<NUM;i++) count2++; } void workerthread3() { for(int i=0;i<NUM;i++) count3.add(1); } void test_performance() { timestamp t1(timestamp::now()); std::thread t[THREAD_NUM]; for(int i=0;i<THREAD_NUM;i++) t[i]=std::thread(workerthread1); for(int i=0;i<THREAD_NUM;i++) t[i].join(); std::cout<<timestamp::now().microSecSinceEpoch()-t1.microSecSinceEpoch()<<" "; std::cout<<count1<<std::endl; t1=timestamp::now(); for(int i=0;i<THREAD_NUM;i++) t[i]=std::thread(workerthread2); for(int i=0;i<THREAD_NUM;i++) t[i].join(); std::cout<<timestamp::now().microSecSinceEpoch()-t1.microSecSinceEpoch()<<" "; std::cout<<count2<<std::endl; t1=timestamp::now(); for(int i=0;i<THREAD_NUM;i++) t[i]=std::thread(workerthread3); for(int i=0;i<THREAD_NUM;i++) t[i].join(); std::cout<<timestamp::now().microSecSinceEpoch()-t1.microSecSinceEpoch()<<" "; std::cout<<count3.get()<<std::endl; } int main() { test_performance(); }