最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11互斥量的具體使用

 更新時(shí)間:2023年11月27日 11:39:17   作者:鏟灰  
互斥量是一種同步原語,是一種線程同步的手段,用來保護(hù)多線程同時(shí)訪問的共享數(shù)據(jù),本文主要介紹了C++11互斥量的具體使用,感興趣的可以了解一下

互斥量是一種同步原語,是一種線程同步的手段,用來保護(hù)多線程同時(shí)訪問的共享數(shù)據(jù)。

C++11中提供了如下4種語義的互斥量(mutex):

1、std::mutex:獨(dú)占的互斥量,不能遞歸使用。

2、std::mutex_mutex:帶超時(shí)的獨(dú)占互斥量,不能遞歸使用。

3、std::recursive_mutex:遞歸互斥量,不帶超時(shí)功能。

4、std::recursive_timed_mutex:帶超時(shí)的遞歸互斥量

獨(dú)占互斥量std::mutex

這些互斥量的基本接口很相似,一般用法是通過lock()方法來阻塞線程,直到獲得互斥量的所有權(quán)為止。在線程獲得互斥量并完成任務(wù)之后,就必須使用unlock()來解除對互斥量的占用,lock()和unlock()必須成對出現(xiàn)。try_lock()嘗試鎖定互斥量,如果成功則返回true,如果失敗則返回false,它是阻塞的。std::mutex的基本用法如下代碼。

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

std::mutex g_lock;

void func()
{
    g_lock.lock();

    cout << "enter thread: " << std::this_thread::get_id() << endl;

    std::this_thread::sleep_for(std::chrono::seconds(1));

    cout << "leaving thread: " << std::this_thread::get_id() << endl;

    g_lock.unlock();
}

///g++ mutex.cpp -lpthread
int main()
{
    std::thread t1(func);
    std::thread t2(func);
    std::thread t3(func);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

輸出結(jié)果如下:

enter thread: 140569127851776
leaving thread: 140569127851776
enter thread: 140568859412224
leaving thread: 140568859412224
enter thread: 140568590972672
leaving thread: 140568590972672

使用lock_guard可以簡化lock/unlock的寫法,同時(shí)也更安全,因?yàn)閘ock_guard在構(gòu)造函數(shù)時(shí)會(huì)自動(dòng)鎖定互斥量,而在退出作用域后進(jìn)行析構(gòu)時(shí)就會(huì)自動(dòng)解鎖,從而保證了互斥量的正確操作,避免忘記unlock操作,因此,應(yīng)盡量用lock_guard。lock_guard用到了RAII技術(shù),這種技術(shù)在類的構(gòu)造函數(shù)中分配資源,在析構(gòu)函數(shù)中釋放資源,保證資源在出了作用域之后就釋放,上面的例子使用lock_guard后更簡潔,代碼如下:

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

std::mutex g_lock;

void func()
{
    std::lock_guard<std::mutex> locker(g_lock);///出了作用域之后自動(dòng)解鎖

    cout << "enter thread: " << std::this_thread::get_id() << endl;

    std::this_thread::sleep_for(std::chrono::seconds(1));

    cout << "leaving thread: " << std::this_thread::get_id() << endl;

}

///g++ mutex.cpp -lpthread
int main()
{
    std::thread t1(func);
    std::thread t2(func);
    std::thread t3(func);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

遞歸的獨(dú)占互斥量std::recursive_mutex

遞歸鎖允許同一個(gè)線程多次獲得該互斥鎖,可以用來解決同一個(gè)線程需要多次獲取互斥量死鎖的問題。在下面的代碼中,一個(gè)線程多次獲取同一個(gè)互斥量時(shí)會(huì)發(fā)生死鎖。

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

struct Complex
{
public:
    Complex(){i = 20;}

    void mul(int x)
    {
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.lock();
        ///std::lock_guard<std::mutex> locker(g_mutex);
        i *= x;
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.unlock();
    }

    void div(int x)
    {
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.lock();
        ///std::lock_guard<std::mutex> locker(g_mutex);
        i /= x;
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.unlock();
    }

    void both(int x, int y)
    {
        ///std::lock_guard<std::mutex> locker(g_mutex);
        g_mutex.lock();
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        mul(x);
        div(y);
        g_mutex.unlock();
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
    }

private:
    int i;
    std::mutex g_mutex;
};


///g++ mutex.cpp -lpthread
int main()
{
    Complex complex;
    complex.both(2, 4);

    return 0;
}

這個(gè)例子運(yùn)行起來就會(huì)發(fā)生死鎖,因?yàn)樵谡{(diào)用both時(shí)獲取了互斥量,之后再調(diào)用mul又要獲取相同的互斥量,但是這個(gè)互斥量已經(jīng)被當(dāng)前線程獲取了,無法釋放,這時(shí)就會(huì)發(fā)生死鎖。要解決這個(gè)死鎖的問題,一個(gè)簡單的辦法就是用遞歸鎖:std::recursive_mutex,它允許同一個(gè)線程多次獲得互斥量。

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

struct Complex
{
public:
    Complex(){i = 20;}

    void mul(int x)
    {
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.lock();
        ///std::lock_guard<std::recursive_mutex> locker(g_mutex);
        i *= x;
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.unlock();
    }

    void div(int x)
    {
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.lock();
        ///std::lock_guard<std::recursive_mutex> locker(g_mutex);
        i /= x;
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        g_mutex.unlock();
    }

    void both(int x, int y)
    {
        ///std::lock_guard<std::recursive_mutex> locker(g_mutex);
        g_mutex.lock();
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        mul(x);
        div(y);
        g_mutex.unlock();
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
    }

private:
    int i;
    std::recursive_mutex g_mutex;
};

void func()
{
    Complex complex;
    complex.both(2, 4);
}

///g++ mutex.cpp -lpthread
int main()
{
    thread t1(func);

    t1.join();

    return 0;
}

需要注意的是盡量不要使用遞歸鎖,主要原因如下:

1、需要用到遞歸鎖定的多線程互斥處理往往本身就是可以簡化的,允許遞歸互斥很容易放縱復(fù)雜邏輯的產(chǎn)生,從而導(dǎo)致一些多線程同步引起的問題。

2、遞歸鎖比起非遞歸鎖,效率會(huì)低一些。

帶超時(shí)的互斥量std::timed_mutex

std::timed_mutex是超時(shí)的獨(dú)占鎖,主要用在獲取鎖時(shí)增加超時(shí)等待功能,因?yàn)橛袝r(shí)不知道獲取鎖需要多久,為了不至于一直在等待獲取互斥量,就設(shè)置一個(gè)等待超時(shí)時(shí)間,在超時(shí)后還可以做其他事情。

std::timed_mutex比std::mutex多了兩個(gè)超時(shí)獲取鎖的接口:try_lock_for和try_lock_until,這兩個(gè)接口是用來設(shè)置獲取互斥量的超時(shí)時(shí)間,使用時(shí)可以用while循環(huán)取不斷地獲取互斥量。std::timed_mutex的基本用法如下所示。

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

std::timed_mutex g_mutex;

void work()
{
    std::chrono::milliseconds timeout(1000);

    while(true)
    {
        if (g_mutex.try_lock_for(timeout))
        {
            cout << std::this_thread::get_id() << ": do work with the mutex" << endl;

            std::chrono::milliseconds sleepDuration(5000);

            std::this_thread::sleep_for(sleepDuration);

            g_mutex.unlock();

            std::this_thread::sleep_for(sleepDuration);
        }
        else
        {
            cout << std::this_thread::get_id() << ": do work without the mutex" << endl;

            std::chrono::milliseconds sleepDuration(2000);

            std::this_thread::sleep_for(sleepDuration);
        }
    }
}


///g++ mutex.cpp -lpthread
int main()
{
    std::thread t1(work);

    std::thread t2(work);

    t1.join();

    t2.join();

    return 0;
}

在上面的例子中,通過一個(gè)while循環(huán)不斷地去獲取超時(shí)鎖,如果超時(shí)還沒有獲取到鎖就會(huì)休眠,再繼續(xù)獲取超時(shí)鎖。

到此這篇關(guān)于C++11互斥量的具體使用的文章就介紹到這了,更多相關(guān)C++11互斥量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C++ STL vector容量(capacity)和大小(size)的區(qū)別

    詳解C++ STL vector容量(capacity)和大小(size)的區(qū)別

    這篇文章主要介紹了詳解C++ STL vector容量(capacity)和大小(size)的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 仿現(xiàn)代C++智能指針實(shí)現(xiàn)引用計(jì)數(shù)

    仿現(xiàn)代C++智能指針實(shí)現(xiàn)引用計(jì)數(shù)

    這篇文章主要為大家詳細(xì)介紹了如何仿現(xiàn)代C++智能指針實(shí)現(xiàn)引用計(jì)數(shù),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以了解下
    2024-03-03
  • 快速學(xué)習(xí)六大排序算法

    快速學(xué)習(xí)六大排序算法

    這篇文章主要介紹了六大排序算法-插入排序、希爾排序、選擇排序、冒泡排序、堆排序、快速排序,需要學(xué)習(xí)的小伙伴可以參考這篇文章
    2021-08-08
  • OpenCV實(shí)現(xiàn)簡易標(biāo)定板

    OpenCV實(shí)現(xiàn)簡易標(biāo)定板

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)簡易標(biāo)定板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • C++深入刨析類與對象的使用

    C++深入刨析類與對象的使用

    類和對象是兩種以計(jì)算機(jī)為載體的計(jì)算機(jī)語言的合稱。對象是對客觀事物的抽象,類是對對象的抽象。類是一種抽象的數(shù)據(jù)類型;變量就是可以變化的量,存儲(chǔ)在內(nèi)存中—個(gè)可以擁有在某個(gè)范圍內(nèi)的可變存儲(chǔ)區(qū)域
    2022-05-05
  • C語言的Struct Hack筆記

    C語言的Struct Hack筆記

    這篇文章主要介紹了C語言的Struct Hack例子,個(gè)人的一篇筆記,需要的朋友可以參考下吧
    2014-04-04
  • 數(shù)據(jù)結(jié)構(gòu) 雙向鏈表的創(chuàng)建和讀取詳解及實(shí)例代碼

    數(shù)據(jù)結(jié)構(gòu) 雙向鏈表的創(chuàng)建和讀取詳解及實(shí)例代碼

    這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) 雙向鏈表的創(chuàng)建和讀取詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Qt Widgets庫的實(shí)現(xiàn)實(shí)例

    Qt Widgets庫的實(shí)現(xiàn)實(shí)例

    QtWidgets 提供了豐富的控件和工具,適合開發(fā)傳統(tǒng)桌面應(yīng)用程序本文主要介紹了Qt Widgets庫的實(shí)現(xiàn)實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-09-09
  • C語言實(shí)現(xiàn)串的順序存儲(chǔ)表示與基本操作

    C語言實(shí)現(xiàn)串的順序存儲(chǔ)表示與基本操作

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)串的順序存儲(chǔ)表示與基本操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Linux網(wǎng)絡(luò)編程之socket文件傳輸示例

    Linux網(wǎng)絡(luò)編程之socket文件傳輸示例

    這篇文章主要介紹了Linux網(wǎng)絡(luò)編程之socket文件傳輸示例,對于基于Linux平臺(tái)的C程序員來說有一定的借鑒價(jià)值,需要的朋友可以參考下
    2014-08-08

最新評(píng)論

宁陵县| 临潭县| 东宁县| 信阳市| 小金县| 拜城县| 泾阳县| 星子县| 兴海县| 盐津县| 阿鲁科尔沁旗| 兴国县| 吴川市| 普安县| 凤台县| 金乡县| 道真| 万载县| 夏邑县| 台前县| 静乐县| 来凤县| 沽源县| 龙南县| 鄢陵县| 潢川县| 高平市| 吴堡县| 剑阁县| 宝山区| 肃南| 宣城市| 广昌县| 平乡县| 维西| 蓬安县| 灌云县| 康保县| 集安市| 青铜峡市| 策勒县|