linux多執行緒 作業系統執行緒同步互斥

2021-08-01 08:56:10 字數 2812 閱讀 3569

這一目主要我想得是理論和實際結合的辦法去做,先將理論,把這塊在作業系統中的內容先進行陳述。然後用linux下的**去真正實現。

perterson演算法是用來是實現對臨界區資源的互斥訪問,它是用軟體的機制實現。也就是說在linux系統程式設計當中,如果不讓你使用pthread_mutex_t mutex你怎麼解決這個問題。perterson演算法給出了軟體實現的方法。

bool flag = ; // flag[i]表示程序i是否想進入臨界區,true表示想進入

int turn; // turn = i,表示可進入臨界區的程序是i

void p0()

}void p1()

}

來分析一下上面這段**,如果因為turn作為公共資源,並且對它本省不加鎖,所以,必然有乙個後訪問它的程序,假設是p1.那就是p0先訪問,p1緊接著就訪問,也就是說其實他們兩都想訪問。但是p0比p1稍微快一點,此時p0進來之後,先表示自己想進臨界區,然後讓對方先進turn=1。p1比p0慢一點,此時p1也想進,那麼flag[1]=true;;turn=0;注意,在turn=0之前,由於p0先執行了,所以p0一直在忙等待,此時turn=0之後,p0進入臨界區,由於turn儲存的是較晚的一次賦值,所以,如果turn=0。表示p1是後進來的,那麼此時p0先進去執行即可。

如果,不存在均要求進入的情況,那就簡單了。

這一塊,主要是參考了本科時的作業系統課本。具體的內容就不多說了,給出偽**我覺得已經很清晰了。

#define n 128        // 緩衝區大小即緩衝池中緩衝區個數

int buffer[n]; // 緩衝池

int front = 0; // 佇列頭

int rear = 0; // 佇列尾下乙個

semaphore mutex = 1; // 互斥訊號量

semaphore full = 0; // 同步訊號量 - 滿緩衝區個數

semaphore empty = n; // 同步訊號量 - 空緩衝區個數

void producer()

void consumer()

/*當然,嚴格的**中,semaphore是結構體。

上面的**只是便於理解。

* */

typedef list_of_process lp; // 這種型別沒有,暫時先這麼寫

typedef semaphoresemaphore_t;

void p( semaphore_t& s )

void v( semaphore_t& s )

補充:這麼搞,在真實寫**的時候有問題吧。雖然生產者和消費者訪問的是不同的單元,但是對於佇列的操作。生產者和消費者可能會有問題吧。一定好把問題分析清楚,這到底是不是讀者-寫者問題?不是!!!因為,訪問的不是同乙個單元。

新的認識

之前對於上面的問題認識的不夠透徹,其實我最近在linux下面寫的**不能算是生產者-消費者。也不是讀者-寫者。它就是兩個寫者,那鎖去控制互斥,訊號量控制同步就可以了。

但是,上面的**,我已經分析清楚了。不是讀者-寫者,因為訪問的並不是同乙個變數。沒有讀-寫的矛盾。

上面的問題就是經典的生產者-消費者問題。只不過我的問題是,你的mutex是幹嘛的?

現在想清楚了,就是加在整個佇列上面的。

因為我之前的理解不是這樣,我認為如果是單生產者和單消費者,是不需要mutex的,因為生產者和消費者本質沒有訪問同乙個變數。所以,他們之間只有同步的語義。互斥的語義是加在生產者與生產者,消費者與消費者之間的。這麼想確實沒有錯,因為不同的生產者要申請單元,不能兩個生產者申請同乙個單元。所以,他們之間需要互斥。消費者同理。

所以,我當初認為,單個生產者單個消費者,和多個生產者多個消費者的區別就在於,前者沒有同類物件之間的鎖。但是,現在,這種想法是不對的。其實,基本上也沒問題。

考慮這樣的乙個場景:對於乙個佇列,有乙個生產者,有乙個消費者。好了,現在,佇列中只有乙個元素。

同時來了生產者和消費者,注意,佇列假設用鍊錶實現。此時,佇列中只有乙個元素。設當前這個節點的指標為p,對於生產者而言,它要在p的後面追加乙個元素,而消費者要釋放p。此時,兩個**都執行了,假設消費者稍快於生產者,釋放了p。而此時生產者由於已經過了判斷佇列是否為空的情形,任然執行p->next = q;那麼,顯然,程式會出錯!

這就是問題,起碼這個是我想到的。對於生產者和消費者而言,佇列上面要加一把鎖。這個鎖可以避免同一類物件申請資源,也可以避免不同物件對於佇列的修改。但是,這樣也會帶來問題,就是生產的時候不能消費,消費的時候不能生產。按理說,他們兩的邏輯是沒關係的。

問題描述:讀者-寫者是這樣的乙個問題。允許多個執行緒同時讀,但是,但是,只允許乙個執行緒寫。也就是說,如果乙個執行緒在寫,那麼其他執行緒不能寫也不能讀。但是,如果乙個執行緒在讀,其他執行緒可以讀,但是不能寫。

問題分析:考慮讀者-寫者之間用互斥實現,這樣可以避免讀者-寫者之間的互斥。此時,讀的時候不能寫,寫的時候不能讀。但是,這麼做會導致,讀的時候也不能讀了。所以,這是問題。在讀者之間還需要實現一定程度的共享。

此時,可以考慮給讀者乙個計數器,當這個計數器不為0的時候,其他讀者只需修改計數器的值,然後去讀就好了。不用等待讀者和寫者之間的鎖。然後讀取操作結束,修改計數器的值即可。在計數器值為0的時候,需要申請和釋放。顯然,不同讀者之間對於這個計數器是共享的,所以也需要互斥訪問。

semaphore_t rmutex = 1;

semaphore_t wmutex = 1;

void reader()

void writer()

多執行緒的作業系統

在支援多執行緒的作業系統中,假設程序p建立了若干個執行緒,那麼 47 是不能被其他執行緒共享的。47 a.該程序的 段 b.該程序中開啟的檔案 c.該程序的全域性變數 d.該程序中線程的棧指標 答案 d 解析 同一程序間的執行緒共享的資源包括 1 堆 由於堆是在程序空間中開闢出來的,所以它是理所當然...

linux 作業系統 pthread 多執行緒庫

include include posix標準的unix標準介面 include pthread t tid1 執行緒id pthread t tid2 void fun1 執行緒函式 void fun2 執行緒函式 int main gcc test.c o test lpthread test1...

Linux作業系統 執行緒

執行緒 在乙個程式裡的乙個執行路線就叫做執行緒。更準確的定義是 執行緒是乙個程序內部的控制序列。一切程序至少都有乙個執行執行緒。程序和執行緒 程序是資源競爭的基本單位。執行緒是程式執行的最小單位。執行緒共享程序資料,但也擁有自己的一部分資料 執行緒id,一組暫存器,棧,errno,訊號遮蔽字,排程優...