windows 多線程

多線程意義:

單核cpu 系統會爲每個線程分配一個時間片,時間片執行完了,就會讓其他線程執行

多核cpu  系統會同時執行幾個線程

單核:在主線程中創建一個子線程,創建完了,子線程爲什麼沒有執行。因爲主線程還在時間片內,所以不會執行子線程。

時間片內主線程會一直執行,直到執行完返回,主線程即進程,執行完了,所有的資源和線程都會被關閉,所以創建的線程就不會執行。
怎麼才能讓創建完的子線程執行呢?
我們只需 sleep(100) sleep一個時間,主線程這段時間就不會執行,新建的子線程就會執行。執行完會返回到主線程,主線程繼續執行。

如果是多核的話:不需要sleep  創建的線程也會執行。


如果分配給線程的時間片到期了,執行權力就會給其他線程。就會斷掉,但是系統會記錄斷掉的位置,任何地方都有可能斷,不管是循環或是判斷語句,其他的線程執行完了,就會返回給當前線程,接着剛纔的地方執行。所以這裏很容易出現問題,比如變量的值或其他已經改變,這裏沒做處理就會出來問題。

模擬這種斷,只需要在想斷的地方加入sleep(1)   就可以斷掉


所以這裏就涉及到線程之間數據同步


互斥對象  


用法:創建一個互斥對象,waitForsignalObject(等待一個互斥對象),release(釋放一個互斥對象),等待一個互斥對象如果該互斥對象被其他線程擁有,該線程就會等待不會執行(這裏的等待,應該會等待,直到時間片執行完畢,另個線程會繼續執行),直到互斥對象可以使用時纔會繼續向下執行。 等待一個互斥對象,一般放在保護代碼的前面,release一般放在關鍵的代碼執行完畢的時候。
互斥對象的管理:是通過引用計數來管理的,當期線程擁有該互斥對象,還調用waitfor... 就會使互斥對象+1,
互斥對象釋放,只有當前線程(因爲互斥對象記錄了當前線程的ID)才能釋放。釋放之後-1, 爲0之後就不會擁有該互斥對象,這時互斥對象就處於有信號狀態。  如果該線程結束(主動結束或返回),就會釋放互斥對象。 waitfor..的返回值,可以判斷該互斥對象是異常終止還是主動終止。
可以利用互斥對象,來限制只能有一個程序運行。


事件對象


分爲人工重置事件對象,與自動重置事件對象
人工重置事件對象,有信號狀態後,會調度所有的等待線程,當前線程獲得當前事件對象,需要手動設置事件對象的信號
自動重置事件對象,有信號狀態後,只會調度一個線程,操作系統會自動把事件對象設置爲無信號,只需在需要的地方設置有信號就可以了。


關鍵代碼段(臨界區)


EnterCriticalSection等待臨界區(判斷是否可用,可用獲取臨界區)
InitializeCriticalSection 初始化臨界區
LeaveCriticalSection 離開臨界區
DeleteCriticalSection 釋放臨界區


線程死鎖
兩個線程,有兩個臨界區(互斥對象或事件對象),
線程1
EnterCriticalSection(A)
sleep(1)    模擬出錯
EnterCriticalSection(B)


線程2
EnterCriticalSection(B)
sleep(1)    模擬出錯
EnterCriticalSection(A)


這樣就造成了死鎖 
線程1獲取A 取得A的擁有權 sleep(1)   會讓線程2執行 線程2獲得B的所有權 
sleep(1) 線程1執行 線程1接着執行,等待B信號, 但是B信號已經被線程2擁有 所以他取得不到 然後一直等待 
線程2繼續執行 等待A信號,但是A信號被線程1擁有,所以他將一直等待下去
這樣程序就不會繼續執行了 造成死鎖


3種同步方式區別



參考:孫鑫vc++視頻 15 16課

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章