c++ atomic 替換鎖

有些文不對題了;

最近搞線程池併發過程中突然想起來用 原子類型 來替換一些mutex, rwlock, cond這些東西;

比如一個reactor 的epoll+線程池[ 例如4個 ], 在發送數據時爲了保證tcp socket的數據順序,

必須加鎖處理 [ 這種模型不容易控制, 實際工程中別用, 對於 socket 還是有一個線程來處理最簡單也避免競爭問題].

然後我發現了個好東西;

下面的測試代碼用 atomic_flag 來替換mutex;

一共沒幾行代碼, 但基本說明了問題.

如果你做併發send(socket,... )  看懂了下面的代碼, 也就知道該怎麼做了

using namespace std;
#include <atomic>

atomic_flag lk  = ATOMIC_FLAG_INIT; //初始化,一開始是false

int g = 0; //全局變量, ++用的

unsigned int  __stdcall th_func(void *arg){
    bool ret = 0;
    int c = 0;
    while(1){
        /*
            test_and_set 的作用:  原子的設置爲 true.
            只有當你設置成功 爲 true時 ,才返回 false ,
            意思是隻有當 lk 爲 false 時, 你才能設置成功,
            否則返回之前的值 : true;
                  
        */

        //原子的設置 true, 50個線程只有一個線程能設置爲true,返回false,其他都返回true
        /* 
             可設置 std::memery_order_relaxed
             不需要保證內存順序, 這裏只要保證 原子性就ok , 因此可隨意他的內存順序.
            
        */
        ret = lk.test_and_set();  //就這一行代碼 ,看懂了就全懂了

        if(!ret){  
// 50個線程中只有唯一一個線程在原子的設置成功後進入
//這裏相當於進入 mutex了

            ++g;
            ++c;
// 把lk原子的設置爲 false , 相當於 unlock
            lk.clear();  
            if(c == 100000)  
                break;
        }

    }

    return 0;
}


int main(int argc, char* argv[])
{

    static const int n = 50;
    HANDLE * arr = new HANDLE[n];

// 起線程
    for(int i = 0; i <  n; ++i){
        arr[i] = (HANDLE)_beginthreadex(0,0,th_func,0,0,0);
    }

    WaitForMultipleObjects(n,arr,TRUE,INFINITE);
    cout << "main done :" << g << endl;
    return 0;
}

 

接下來的問題就容易解決了,

在線程池中:

ret = lk.test_and_set();
if(!ret){
    send / write
}
else{
    仍回隊列 / 某個容器裏
    
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章