學習點滴 c 三個執行緒迴圈列印ABC

2021-09-25 16:38:24 字數 3418 閱讀 8908

用上了實驗室新買的伺服器,美滋滋

小試牛刀一番

#include#includeusing namespace std;

pthread_mutex_t mutex;

int k=0; //全域性區變數是共享的哦

pthread_cond_t cond = pthread_cond_initializer;

void *func1(void *arg)

cout<<"a";

k++;

pthread_mutex_unlock(&mutex);

pthread_cond_broadcast(&cond);

}}void *func2(void *arg)

cout<<"b";

k++;

pthread_mutex_unlock(&mutex);

pthread_cond_broadcast(&cond);

}}void *func3(void *arg)

cout<<"c";

k++;

pthread_mutex_unlock(&mutex);

pthread_cond_broadcast(&cond);

}}int main(){

pthread_mutex_init(&mutex, null);

pthread_t tid1;

pthread_t tid2;

pthread_t tid3;

pthread_create(&tid1,null,func1,null);

pthread_create(&tid2,null,func2,null);

pthread_create(&tid3,null,func3,null);

// cout<<"pthread create success!"《用了mutex和條件變數cond,乙個比較簡單的多執行緒程式。

makefile如下:

source := $(wildcard *.cpp)

objs := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(source))) #在objs中 把.cpp和.c的檔案變成.o的字尾

target := test

cc := g++

libs := -lpthread

#include:= -i./usr/local/include/opencv

cflags := -std=c++11 -g -wall #-o3 #$(include)

cxxflags:= $(cflags)

.phony : objs clean veryclean rebuild all

all : $(target)

objs : $(objs)

rebuild: veryclean all

clean :

rm -fr *.o

veryclean : clean

rm -rf $(target)

$(target) : $(objs) #最終目標

$(cc) $(cxxflags) -o $@ $(objs) $(ldflags) $(libs)

pthread_cond_signal 與 pthread_cond_broadcast:

1,pthread_cond_signal在多處理器上可能同時喚醒多個執行緒,當你只能讓乙個執行緒處理某個任務時,其它被喚醒的執行緒就需要繼續 wait,while迴圈的意義就體現在這裡了,而且規範要求pthread_cond_signal至少喚醒乙個pthread_cond_wait上 的執行緒,其實有些實現為了簡單在單處理器上也會喚醒多個執行緒. 

2,某些應用,如執行緒池,pthread_cond_broadcast喚醒全部執行緒,但我們通常只需要一部分執行緒去做執行任務,所以其它的執行緒需要繼續wait.所以強烈推薦此處使用while迴圈.

其實說白了很簡單,就是pthread_cond_signal()也可能喚醒多個執行緒,而如果你同時只允許乙個執行緒訪問的話,就必須要使用while來進行條件判斷,以保證臨界區內只有乙個執行緒在處理。

c++執行緒的幾種鎖:

具體見執行緒之間的鎖有:互斥鎖、條件鎖、自旋鎖、讀寫鎖、遞迴鎖。一般而言,鎖的功能與效能成反比。不過我們一般不使用遞迴鎖(c++標準庫提供了std::recursive_mutex),所以這裡就不推薦了。

互斥鎖

在某一時刻,只有乙個執行緒可以獲取互斥鎖,在釋放互斥鎖之前其他執行緒都不能獲取該互斥鎖。如果其他執行緒想要獲取這個互斥鎖,那麼這個執行緒只能以阻塞方式進行等待。

條件鎖

自旋鎖

在對乙個已經被持有的鎖進行加鎖時,執行緒不會阻塞,而是原地自旋,始終占用cpu

前面的兩種鎖是比較常見的鎖,也比較容易理解。下面通過比較互斥鎖和自旋鎖原理的不同,這對於真正理解自旋鎖有很大幫助。假設我們有乙個兩個處理器core1和core2計算機,現在在這台計算機上執行的程式中有兩個執行緒:t1和t2分別在處理器core1和core2上執行,兩個執行緒之間共享著乙個資源。

首先我們說明互斥鎖的工作原理,互斥鎖是是一種sleep-waiting的鎖。假設執行緒t1獲取互斥鎖並且正在core1上執行時,此時執行緒t2也想要獲取互斥鎖(pthread_mutex_lock),但是由於t1正在使用互斥鎖使得t2被阻塞。當t2處於阻塞狀態時,t2被放入到等待佇列中去,處理器core2會去處理其他任務而不必一直等待(忙等)。也就是說處理器不會因為執行緒阻塞而空閒著,它去處理其他事務去了。

而自旋鎖就不同了,自旋鎖是一種busy-waiting的鎖。也就是說,如果t1正在使用自旋鎖,而t2也去申請這個自旋鎖,此時t2肯定得不到這個自旋鎖。與互斥鎖相反的是,此時執行t2的處理器core2會一直不斷地迴圈檢查鎖是否可用(自旋鎖請求),直到獲取到這個自旋鎖為止。

從「自旋鎖」的名字也可以看出來,如果乙個執行緒想要獲取乙個被使用的自旋鎖,那麼它會一致占用cpu請求這個自旋鎖使得cpu不能去做其他的事情,直到獲取這個鎖為止,這就是「自旋」的含義。當發生阻塞時,互斥鎖可以讓cpu去處理其他的任務;而自旋鎖讓cpu一直不斷迴圈請求獲取這個鎖。通過兩個含義的對比可以我們知道「自旋鎖」是比較耗費cpu的。

讀寫鎖

讀鎖共享,寫鎖獨佔

說到讀寫鎖我們可以借助於「讀者-寫者」問題進行理解。首先我們簡單說下「讀者-寫者」問題。

計算機中某些資料被多個程序共享,對資料庫的操作有兩種:一種是讀操作,就是從資料庫中讀取資料不會修改資料庫中內容;另一種就是寫操作,寫操作會修改資料庫中存放的資料。因此可以得到我們允許在資料庫上同時執行多個「讀」操作,但是某一時刻只能在資料庫上有乙個「寫」操作來更新資料。這就是乙個簡單的讀者-寫者模型。

三個執行緒,依次列印

程式設計實現三個執行緒abc,並讓它們順次列印abc 思路 設定三個訊號量 s1,s2,s3,s2由s1 post,s3由s2 post,s1由s3 post,由a執行緒先開始列印,其他執行緒必然在等待訊號量,所以三個執行緒一定會按照訊號量的順序來列印。注意vs 2015中多執行緒使用要呼叫wind...

C 三個迴圈

迴圈在很多時候都起到了很大的作用,是乙個很重要的語法結構 首先在c 中接觸到了三種迴圈結構他們分別是 1 while迴圈 這種迴圈的用法是先判斷然後再執行迴圈體,2 do while迴圈 這種迴圈是先執行一次迴圈體,然後再判斷條件是否成立 3 for 迴圈 這個迴圈是在知道迴圈的次數後可以選擇使用這...

從三個執行緒 排隊列印 , 到 多個執行緒列印

第一中 大暴力 直接 while 迴圈 判斷mark private static class two implements runnable override public void run static void start for int i 0 i n i 第二種 利用 reentrantl...