muduo原始碼解析2-AtomicIntegerT類
阿新 • • 發佈:2020-08-22
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(); }