使用執行緒編寫程式需要技巧,而多執行緒的程式中的bug非常難以跟蹤、除錯,因為這些bug經常是難以再現的。
競爭條件
:當乙個執行緒訪問乙個資料結構的時候,另乙個執行緒也訪問同乙個資料結構,這時就出現了競爭條件——兩個執行緒(也可能是多個)競爭對同乙個資源的訪問。
當其中乙個執行緒處理到一部分的時候,另外的執行緒可能進入了對同一資料的處理,而且出於排程的原因,它執行的比前乙個更快;這時,同樣的處理可能就出現了多次。
例如,乙個代表任務列表的單向鍊錶(佇列),乙個執行緒從當前元素中讀出了下乙個任務,並發現下乙個任務不是空,準備將此乙個任務置為null並執行任務; 這時,排程使得這個執行緒停下來,另乙個執行緒也從當前元素中讀出了下乙個任務,當然下個任務仍然不是空值,這個執行緒也將要執行下乙個任務。這樣,在某些不幸 的情況下,這個任務被執行了兩次。
更為不幸的情況下,執行任務的過程中線程被中斷,此時另乙個執行緒釋放了任務的記憶體,那麼執行中的執行緒會導致段錯誤。
在比較「幸運」的情況下,這些事情可能從來也不發生;但是當程式執行在負荷很高的系統中時,這個bug就會凸現出來。
互斥鎖:
為了排除競爭條件的影響,應該使一些操作變成「原子的」——這些操作既不能分割也不能中斷。
當乙個執行緒鎖定了互斥鎖後,其他執行緒也要求鎖定這個互斥鎖的時候,就會被阻塞;直到前面的執行緒解除鎖定後,其他執行緒才可以解除阻塞恢復執行。
gnu/linux保證執行緒在鎖定互斥鎖的過程中不會發生競爭條件,只有乙個執行緒可以鎖定互斥鎖,其他執行緒的鎖定請求都會被阻塞。
建立互斥鎖(mutex),需要:
`建立乙個pthread_mutex_t型別的變數,將其指標傳入函式pthread_mutex_init中;該函式的第二個引數是指向乙個mutex屬性物件(這個物件用來指定mutex的屬性)的指標。mutex物件只能初始化一次。
`更簡單的辦法是,使用pthread_mutex_initializer來獲得預設屬性的mutex物件:
pthread_mutex_t mutex = pthread_mutex_initializer;
使用mutex:
`呼叫pthread_mutex_lock函式,如果mutex物件未被鎖定,則此函式立即返回;如果已被鎖定,則此函式阻塞此執行緒的執行,直到mutex被解除鎖定。
`每次解除鎖定後,只有乙個執行緒可以解除阻塞恢復執行,其他呼叫執行緒都會繼續阻塞。選定的解除阻塞的執行緒是不可預知的。
`呼叫pthread_mutex_unlock函式,可以解除呼叫執行緒對mutex物件的鎖定。在鎖定mutex的執行緒中,必須呼叫此函式以解除鎖定。
mutex提供了解決競爭條件的方案,但是它帶來了一種新的bug——死鎖(
deadlock
)。所謂死鎖,就是說乙個執行緒在等待永遠不會發生的條件。
乙個簡單的死鎖:乙個執行緒鎖定它自己已經鎖定的mutex。這時程式的表現依賴於mutex的型別:
`快速排他鎖(fast mutex)——導致死鎖。
`遞迴排他鎖(recursive mutex)——不導致死鎖。同乙個執行緒可以安全的多次鎖定同乙個已鎖定的mutex,但是鎖定的次數會被記錄下來,該執行緒還必須呼叫相應次數的pthread_mutex_unlock才能真正解除對mutex的鎖定。
`檢錯排他鎖(error-checking mutex)——gnu/linux視此操作為死鎖,但是對鎖定的mutex呼叫pthread_mutex_lock函式,函式立即返回錯誤碼edeadlk。
mutex的鎖定函式會阻塞,有時需要乙個不阻塞就能知道mutex是否已鎖定的函式,以在發現mutex已鎖的情況下去完成其他工作並在以後再來檢查。這樣的函式是:
pthread_mutex_trylock
如果傳入的mutex已經被其他執行緒鎖定,那麼這個函式返回錯誤碼ebusy;如果未被鎖定,此函式會鎖定mutex,並返回0。這個函式不會阻塞。
linux 執行緒互斥鎖
一,鎖的建立 鎖可以被動態或靜態建立,可以用巨集pthread mutex initializer來靜態的初始化鎖,採用這種方式比較容易理解,互斥鎖是pthread mutex t的結構體,而這個巨集是乙個結構常量,如下可以完成靜態的初始化鎖 pthread mutex t mutex pthrea...
Linux執行緒互斥鎖
一,鎖的建立 鎖可以被動態或靜態建立,可以用巨集pthread mutex initializer來靜態的初始化鎖,採用這種方式比較容易理解,互斥鎖是pthread mutex t的結構體,而這個巨集是乙個結構常量,如下可以完成靜態的初始化鎖 pthread mutex t mutex pthrea...
Linux執行緒 互斥鎖
pthread mutex init,pthread mutex destory,pthread mutex lock,pthread mutex unlock這幾個函式以完成鎖的初始化,鎖的銷毀,上鎖和釋放鎖操作。鎖可以被動態或靜態建立,可以用巨集pthread mutex initializer...