程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 一起talk C栗子吧(第一百一十七回:C語言實例

一起talk C栗子吧(第一百一十七回:C語言實例

編輯:關於C

各位看官們,大家好,上一回中咱們說的是線程同步之互斥量的例子,這一回咱們說的例子是:線程死鎖。閒話休提,言歸正轉。讓我們一起talk C栗子吧!

我們在前面章回中介紹互斥量相關的函數時提到過死鎖,不過當時沒有做詳細的介紹,有些看官對死鎖不明白。因此,我們在今天的章回中詳細介紹死鎖,並且使用線程來顯示死鎖。

死鎖就是不同的程序在運行時因為某種原因發生了阻塞,進而導致程序不能正常運行。阻塞程序的原因通常都是由於程序沒有正確使用臨界資源。

我們舉個日常生活中的例子來比喻死鎖。我們把馬路上行駛的汽車比作運行著的程序,把馬路比作臨界資源,如果有兩輛汽車相互碰撞,就會把車停在馬路上,這樣的話他們一直占用著馬路這個臨界資源。其它的汽車不能正常通過馬路,於是整條路上的汽車都無法在馬路上正常行駛,馬路也被汽車堵的水洩不通。整個交通都癱瘓了,這就是“死鎖”。造成死鎖的原因就是發生車禍的汽車占用了馬路這種臨界資源,以至於其它汽車無法在馬路上正常行駛。

在實際的程序中造成死鎖的原因有兩種

同一個線程對已經加鎖的互斥量再次加鎖; 線程A對互斥量一加鎖,同時等待互斥量二被解鎖;而此時,線程B對互斥量二加鎖,同時等待互斥量一被解鎖;

第一種原因相對來說容易避免,畢竟在同一個線程中,避免兩次加鎖操作還是容易做到的。此外,我們還可以使用嘗試性加鎖函數:pthread_mutex_trylock對互斥量加鎖。

我們寫一個偽代碼來演示死鎖

thread_func() //線程執行函數
{

    lock(mutex_value);  //第一次對互斥量進行加鎖
    //do some thing
    lock(mutex_value);  //第二次對互斥量進行加鎖,死鎖發生
    // do another thing
    unlock(mutex_value); //對互斥量進行解鎖操作
    unlock(mutex_value);
}

第二種原因就不容易發現了,線程A鎖著互斥量一不放,同時等待互斥量二被解鎖;而線程B鎖著互斥量二不放,同時等待互斥量一被解鎖。它們都在等待互斥量被解鎖,但是卻不肯對被自己加鎖的互斥量進行解鎖操作,因此就發生了死鎖。這種死鎖是在兩個線程中操作不同的互斥量造成的,因此不容易被發現。這就需要我們不斷地積累經驗來避免死鎖發生。

我們寫一個偽代碼來演示死鎖

thread_funcA() //線程A的執行函數
{

    lock(mutex_value1);  //對互斥量一進行加鎖
    //do some thing
    lock(mutex_value2);  //對互斥量二進行加鎖,等待互斥量二被解鎖
    // do another thing
    unlock(mutex_value2); //對互斥量二進行解鎖操作
    unlock(mutex_value1); //對互斥量一進行解鎖操作
}
thread_funcB() //線程B的執行函數
{

    lock(mutex_value2);  //對互斥量二進行加鎖
    //do some thing
    lock(mutex_value1);  //對互斥量一進行加鎖,等待互斥量一被解鎖
    // do another thing
    unlock(mutex_value1); //對互斥量一進行解鎖操作
    unlock(mutex_value2); //對互斥量二進行解鎖操作
}

程序發生死鎖後就會一直阻塞,直到消耗完系統資源為止。因此,我們一定要正確使用互斥量以及線程,不然會在程序中造成嚴重的錯誤。

各位看官,關於死鎖的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved