11-1和11-2的具體區別?
portion -> 部分程序員
什麼是分離?
在任何一個時間點上,線程是可結合的(joinable),或者是分離的(detached)。一個可結合的線程可以被其餘線程收回其資源和殺死;在被其餘線程回收以前,它的存儲器資源(如棧)是不釋放的。相反,一個分離的線程是不能被其餘線程回收或殺死的,它的存儲器資源在它終止時由系統自動釋放。
線程的分離狀態決定一個線程以什麼樣的方式來終止本身。在上面的例子中,咱們採用了線程的默認屬性,即爲非分離狀態(便可結合的,joinable,須要回收),這種狀況下,原有的線程等待建立的線程結束;只有當pthread_join()函數返回時,建立的線程纔算終止,才能釋放本身佔用的系統資源。而分離線程不是這樣子的,它沒有被其餘的線程所等待,本身運行結束了,線程也就終止了,立刻釋放系統資源。程序員應該根據本身的須要,選擇適當的分離狀態。
總之爲了在使用 pthread 時避免線程的資源在線程結束時不能獲得正確釋放,從而避免產生潛在的內存泄漏問題,在對待線程結束時,要確保該線程處於 detached 狀態,否着就須要調用 pthread_join() 函數來對其進行資源回收。編程
靜態分配和動態分配?
靜態分配發生在程序編譯和鏈接的時候。動態分配則發生在程序調入和執行的時候。
堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,好比局部變量的分配。動態分配由函數malloc進行分配。不過棧的動態分配和堆不一樣,他的動態分配是由編譯器進行釋放,無需咱們手工實現。 函數
互斥鎖mutex
用於保證在任什麼時候刻,都只能有一個線程訪問該對象。當獲取鎖操做失敗時,線程會進入睡眠,等待鎖釋放時被喚醒
互斥鎖是用於線程的互斥的.net
自旋鎖:spinlock
在任什麼時候刻一樣只能有一個線程訪問對象。可是當獲取鎖操做失敗時,不會進入睡眠,而是會在原地自旋,直到鎖被釋放。這樣節省了線程從睡眠狀態到被喚醒期間的消耗,
在加鎖時間短暫的環境下會極大的提升效率。但若是加鎖時間過長,則會很是浪費CPU資源線程
讀寫鎖:rwlock
區分讀和寫,處於讀操做時,能夠容許多個線程同時得到讀操做。可是同一時刻只能有一個線程能夠得到寫鎖。其它獲取寫鎖失敗的線程都會進入睡眠狀態,直到寫鎖釋放時被喚醒。
注意:寫鎖會阻塞其它讀寫鎖。當有一個線程得到寫鎖在寫時,讀鎖也不能被其它線程獲取;寫優先於讀,當有線程由於等待寫鎖而進入睡眠時,則後續讀者也必須等待
適用於讀取數據的頻率遠遠大於寫數據的頻率的場合。rest
信號量:semaphore
是用於線程間同步的,當一個線程完成操做後就經過信號量通知其它線程,而後別的線程就能夠繼續進行某些操做了。
信號量是用於線程間同步,也就是調度線程的,code
帶有超時的讀寫鎖
長時間沒有拿到鎖,返回ETIMEDOUT對象
條件變量
條件變量是利用線程間共享的全局變量進行同步的一種機制。
例如讀者寫者問題,讀者在消息隊列爲空時,會利用pthread_cond_wait掛起,等待寫者寫入隊列,並傳送pthread_cond_signal,再被喚醒,進行讀的工做。
參考UNIX環境高級編程圖11-15blog
屏障
屏障(barrier)是用戶協調多個線程並行工做的同步機制。屏障容許每一個線程等待,直到全部的合做線程都達到某一點,而後從該點繼續執行。隊列
int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned count);
初始化屏障時,能夠使用count參數指定,在容許全部線程繼續運行以前,必須到達屏障的線程數目。
使用內存屏障,以強制該語句先後的指令以正確的次序完成
a++; b=f(a); c--;
上句不使用屏障時,可能會如下面的順序執行。
a++; c--; b=f(a);
可是沒有問題。
obj->data = xxx; obj->ready = 1;
當設置了data以後,記下標誌,而後在另外一個線程中可能執行:
if (obj->ready) do_something(obj->data);
若是標誌被置位先於data被設置,那麼結果是收到了do_something(未修改的obj->data)。
這時候就須要強制語句前後順序.
pthread_barrier_init(barrier,NULL,2);
obj->data = xxx; obj->ready = 1;pthread_barrier_wait(*barrier);
pthread_barrier_wait(*barrier);if (obj->ready) do_something(obj->data);