C++ 自旋鎖簡單實現

C++11 版不帶自旋鎖的API,我們可以手動實現,有的時候線程執行的功能比較簡單,或者說代碼量較少,如果使用mutex的話,開銷比較大,但是使用mutex的鎖,線程處於非運行態時不佔用CPU,這是其他的線程可以運行,使用自旋鎖時線程被阻塞,但是被阻塞線程依然不會讓出CPU,而是會不斷的while來檢查鎖的狀態,有點浪費CPU,所以自旋鎖一般適用於簡短的不耗時的線程

自旋鎖可以使用如下方式來實現:

class spin_lock {
private:
    atomic_flag flag;
public:
    spin_lock() = default;
    spin_lock(const spin_lock&) = delete;
    spin_lock& operator=(const spin_lock) = delete;
    void lock() {   //acquire spin lock
        while (flag.test_and_set());
    }
    void unlock() {   //release spin lock
        flag.clear();
    }
};

atomic_flag是原子操作的,獲得鎖後會把此變量置爲true,然後另外一個進程就會因爲flag=true而一直在while處執行循環,知道獲得鎖的線程將鎖釋放(將falg置爲false),此時線程的flag.test_and_set()就會返回false,跳出while循環,並把flag置爲true,使用如下:

// 02自旋鎖.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <thread>
#include <atomic>
#include <iostream>
#include <cstdio>
using namespace std;
using namespace this_thread;
using namespace chrono;

class spin_lock {
private:
    atomic_flag flag;
public:
    spin_lock() = default;
    spin_lock(const spin_lock&) = delete;
    spin_lock& operator=(const spin_lock) = delete;
    void lock() {   //acquire spin lock
        while (flag.test_and_set());
    }
    void unlock() {   //release spin lock
        flag.clear();
    }
};

int num = 0;
spin_lock splock;
void func()
{
    for (int i = 0; i < 100000; ++i)
    {
        splock.lock();
        ++num;
        //sleep_for(milliseconds(100));
        splock.unlock();
    }
}

int main()
{
    cout << "程序開始執行" << endl;
    thread t1(func);
    thread t2(func);
    thread t3(func);
    t1.join();
    t2.join();
    t3.join();
    cout << num << endl;
    return 0;
}

這裏寫圖片描述
另外需要注意的是,在鎖中不能加休眠,假如加入休眠,線程A獲得鎖之後進行休眠,此時並未釋放鎖,flag還是true,但是在CPU調度下會執行線程B,線程B此時就會檢查鎖的狀態,由於A並沒有釋放鎖,所以線程B會死在while中,導致CPU無法調度運行其他線程,也就無法運行線程A的解鎖,如此會產生死鎖

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