1. 程式人生 > 實用技巧 >muduo原始碼解析2-AtomicIntegerT類

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();

}