欧美日韩在线第一页-欧美日韩在线观看精品-欧美日韩在线观看一区二区-欧美日韩在线免费看-欧美日韩在线视频不卡一区二区三区

編程代碼
新聞詳情

C++11多線程編程(七)——信號量的實現

發布時間:2021-01-07 14:00:00 瀏覽次數:2416

一、為何需要信號量

信號量用來干嘛的呢?搜尋答案的話,很多人都會告訴你主要用于線程同步的,意思就是線程通信的。簡單來說,比如我運行了2個線程A和B,但是我希望B線程在A線程之前執行,那么我們就可以用信號量來處理。有些人可能會疑惑,那么麻煩干嘛?你不是要B線程先執行嗎?那么我讓A線程休眠一點時間不就可以了嗎?沒錯,這個思路是可以的,但是如果B線程也因為某些原因(比如硬件,操作系統的原因)導致延緩執行了,這該怎么辦?到底A線程該休眠多少時間合適呢?所以正確的做法就是在B線程阻塞,A線程去喚醒這個阻塞線程。


看到這兒,看過我前面文章的朋友可能一眼就看出來了這個不就是前面講的生產消費者模型提到的用法嗎?

沒錯,信號量的實現也是靠條件變量和互斥鎖。

所以雖然C++中并沒有在語言級別上支持信號量,但同樣的我們可以利用以上兩個來自己實現一個。

這里我也不得不提一句,條件變量和互斥鎖組合使用真的非常強大,生產消費者模型中用到了,線程池中用到了,現在說的信號量也用到了,所以大家一定要好好掌握條件變量和互斥鎖的使用,它們倆是你在多線程世界中縱橫捭闔的利劍。

二、信號量的實現

那么我們如何用C++來實現一個信號量呢?

#ifndef _SEMAPHORE_H
#define _SEMAPHORE_H
#include <mutex>
#include <condition_variable>
using namespace std;
 
class Semaphore
{
public:
    Semaphore(long count = 0) : count(count) {}
    //V操作,喚醒
    void signal()
    {
        unique_lock<mutex> unique(mt);
        ++count;
        if (count <= 0)
            cond.notify_one();
    }
    //P操作,阻塞
    void wait()
    {
        unique_lock<mutex> unique(mt);
        --count;
        if (count < 0)
            cond.wait(unique);
    }
    
private:
    mutex mt;
    condition_variable cond;
    long count;
};
#endif

信號量里面用到了一個叫PV操作的東西,P操作時阻塞,一般用wait()函數,V操作是喚醒,一般用singal()函數,至于不叫WS操作,反而為什么叫PV操作呢?網上說是因為提出這一系統方法的人狄克斯特拉用荷蘭文定義的,因為在荷蘭文中,通過叫passeren,釋放叫vrijgeven,PV操作因此得名。對我們來說,這些也沒有太大的意義,記住這些定義就好了,畢竟定義這種東西,是不以我們的意志為轉移的。

寫好了信號量的接口,那我們如何使用這個信號量呢?這個就需要我們在外部寫一個多線程的調用函數來調用。

#include "semaphore.h"
#include <thread>
#include <iostream>
using namespace std;
 
Semaphore sem(0);
 
void funA()
{
    sem.wait();
    //do something
    cout << "funA" << endl;
}
 
void funB()
{
    this_thread::sleep_for(chrono::seconds(1));
    //do something
    cout << "funB" << endl;
    sem.signal();
}
 
int main()
{
    thread t1(funA);
    thread t2(funB);
    t1.join();
    t2.join();
}

三、信號量解析

這里我們想讓funB線程運行,然后再運行funA,多線程是通過時間片輪詢來執行的。

假設先開始跑funA,執行到sem.wait()的時候,進入wait函數可知,count減1,小于0,會發生阻塞,等待其他線程喚醒。

然后就會切換到funB,這里即使休眠了1秒也不會切換到funA,因為那邊阻塞了,沒有其他線程喚醒的話就會一直阻塞。funB休眠完之后,就會打印出結果,然后執行sem.signal(),進入signal函數可知,count加1,小于等于0,會喚醒其他阻塞的線程。

然后再切到funA,執行后面的操作,打印出結果。

所以這個就一定能保證funB先執行,funA后執行。當然前提是初始化信號量對象的時候,要初始化為0。

Semaphore sem(0);

信號量用在多線程多任務同步的,一個線程完成了某一個動作就通過信號量告訴別的線程,別的線程再進行某些動作。像這里funB完成任務之后就通過信號量的PV操作告訴funA線程可以開始任務了。

最后需要注意的是,信號量不僅可以用于進程也可用于線程,它比條件變量要復雜很多,條件變量僅限于線程內使用,至于進程間如何使用信號量通信,后期我們在討論。

在線客服 雙翌客服
客服電話
  • 0755-23712116
  • 13822267203
主站蜘蛛池模板: 99ri国产在线观看| 免费看大片的| 91精品国产91久久久久福利| 国产 另类 在线 欧美日韩| 男女全黄做爰视频免费看| 日韩免费视频网站| 亚洲精品成人一区二区aⅴ| 达达兔午夜国产精品| 国产精品三级a三级三级午夜| 在线观看欧美大片| 一级坐爱片| 久久婷婷色香五月综合激情| 性欧美videosg最新另类| 在线观看一级毛片| 一区二区三区亚洲| 国产r级| 欧美成人做性视频在线播放| 日韩三区| 日本内谢69xxxx免费播放| 黄色一集片| 免费jizz在线播放视频高清版| 一级毛片在线播放| 国产中出| 国产精品一区在线观看| 亚洲一区二区三区久久久久| 亚洲经典在线观看| 婷婷中文| 成人免费片| 亚洲婷婷综合中文字幕第一页| 国产精品爽爽影院在线| 国内三级视频| 三级黄色片在线免费观看| 欧美日韩国产在线人| 视频一区二区三区蜜桃麻豆| 成人毛片18女人毛片免费| 中文字幕国产欧美| chinese国产hdfree中文| 免费网站看v片在线香蕉| 一级做a爰毛片| 国产又色又爽又黄又刺激18| 国产一级在线视频|