併發易混淆概念總結

2021-08-14 12:26:47 字數 2384 閱讀 6544

執行緒a執行邏輯經過x邏輯,執行緒b執行邏輯經過y邏輯。

競爭: 程式執行結果的正確性,取決於b的y邏輯必須要在a的x邏輯前執行,此時就發生了競爭。

感覺這麼解釋還是比較抽象,下面通過乙個c語言的例子來解釋:

a執行緒通過for迴圈建立多個對等執行緒,x邏輯表示建立對等執行緒並傳遞引數。

b執行緒得到a執行緒傳遞的引數,y邏輯表示列印傳遞的引數。

#include "test.h"

#define n 4

void *thread(void vargp);

//以下為a執行緒

int main()

for(i = 0; i < n; i++)

exit(0);

}//執行緒b

void *thread(void *vargp)

實際結果:

>./test

hello from thread 1

hello from thread 3

hello from thread 2

hello from thread 3

原因:

主線程(a)和對等執行緒(b)之間存在競爭,導致程式最終執行的結果和預期的是不一致的。a執行緒傳遞乙個指向本地棧變數的i指標到b 執行緒。如果b執行緒y邏輯(vargp引數的間接引用和賦值)能夠每次都在a執行緒x邏輯(對i加1的操作)那麼myid就能夠得到正確的id。

解決方案:

可以將執行緒a的&i的傳遞改為傳遞堆空間的值,注意在b執行緒必須釋放堆的記憶體,否則會造成記憶體洩露。

執行緒安全函式:乙個函式被稱為執行緒安全的, 當且僅當被多個併發執行緒反覆地呼叫時,它會一直產生正確的結果。

執行緒安全不是很好判斷,我們先來理解下它的補集——執行緒不安全。乙個函式不是執行緒安全就是執行緒不安全的。所以只要學會判斷乙個函式是不是執行緒不安全的就可以了。

定義四類執行緒不安全的函式類

可重入函式,其特點在於它們具有被多個執行緒呼叫時,不會引起任何共享資料的特性。

感覺說完了,你不能說它的定義是錯的但是還是不清楚什麼函式是可重入函式。簡單點,概念不要這麼複雜簡單點,就是這個函式能夠被再次進入唄!

舉個例子:

執行緒a– ———–>函式f1()————-中斷—————–>函式f1()

*可重入函式也可以這樣理解,重入即表示重複進入,首先它意味著這個函式可以被中斷,其次意味著它除了使用自己棧上的變數以外不依賴於任何環境(包括static),這樣的函式就是purecode(純**)可重入,可以允許有多個該函式的副本在執行,由於它們使用的是分離的棧,所以不會互相干擾。如果確實需要訪問全域性變數(包括static),一定要注意實施互斥手段。可重入函式在並行執行環境中非常重要,但是一般要為訪問全域性變數付出一些效能代價

總結下執行緒安全、執行緒不安全和可重入函式的關係。

可重入函式一定是執行緒安全函式,但執行緒安全函式不一定是可重入函式。其實很好理解,可重入函式一定是沒有共享全域性變數的符合執行緒安全函式的第一和第三點要求。

什麼是死鎖

死鎖:是指兩個或兩個以上的程序(或執行緒)在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。

死鎖發生的條件

舉個例子

執行緒a,執行緒b,互斥鎖s1,互斥鎖s2,a,b執行緒均需要獲取兩個鎖才能繼續執行。

執行緒a獲取互斥鎖s1的使用權,同時執行緒b獲得互斥鎖s2的使用權。此時執行緒a、執行緒b均等待對方釋放自己需要的鎖,但是ab又都不肯釋放自己的鎖,此時就處於死鎖的狀態。

什麼是飢餓

飢餓:是指如果執行緒t1占用了資源r,執行緒t2又請求封鎖r,於是t2等待。t3也請求資源r,當t1釋放了r上的封鎖後,系統首先批准了t3的請求,t2仍然等待。然後t4又請求封鎖r,當t3釋放了r上的封鎖之後,系統又批准了t4的請求……,t2可能永遠等待。

舉個例子

讀者寫者的問題上,如果是讀者優先,那麼寫者就可能一直處於飢餓的狀態。

讀者a先進入,寫者b等待資源,但此時不斷有讀者進入,導致資源一直被占用無法釋放,於是寫者b就處於飢餓的狀態。

死鎖和飢餓的區別執行緒是否是一直處於阻塞的狀態還是有可能從阻塞狀態變為非阻塞狀態只是時間未可知。

易混淆的幾個概念

不知道行不行,大家看下,指點下 謝謝額 1.抽象方法與介面 第乙個還沒寫,那個寫一下貼上來 2.多型與繼承 3.委託類及說明委託 匿名委託 4.反射的方法訪問另乙個類的方法。一 開發oa系統中有公文流轉流程,其中在公文流轉中有公文審核,公文審核是按級審核的,比如發文單位主管審核後,經理要審核,經理審...

Delphi 易混淆的概念

一 owner和parent的區別 parent屬性是指構件的包容器,構件只能在此範圍內顯示和移動。舉例子如下 1 在form1的窗體上,放乙個panel1,並將panel1拉大,2 在panel1上放一button1 3 在form1上放一button2。現在如果移動panel1,則button1...

jQuery中易混淆 錯誤理解概念總結(逐漸新增)

一 attr attrname,function index,oldvalue 中index值 我們都知道.attr 方法中的通過返回值修改原屬性的值的函式中的oldvalue指的是元素修改前的值 但是很少能找到index值的用法的例項,只是簡單說明了index是選中元素在同級元素中的索引值。這個概...