一。互斥量和條件變數簡介
互斥量(mutex)從本質上說是一把鎖,在訪問共享資源前對互斥量進行加鎖,在訪問完成後釋放互斥量上的鎖。對互斥量進行加鎖以後,任何其他試圖再次對互斥鎖加鎖的執行緒將會阻塞直到當前執行緒釋放該互斥鎖。如果釋放互斥鎖時有多個執行緒阻塞,所有在該互斥鎖上的阻塞執行緒都會變成可執行狀態,第乙個變為執行狀態的執行緒可以對互斥鎖加鎖,其他執行緒將會看到互斥鎖依然被鎖住,只能回去再次等待它重新變為可用。
條件變數(cond)是在多執行緒程式中用來實現"等待--》喚醒"邏輯常用的方法。條件變數利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個動作:乙個執行緒等待"條件變數的條件成立"而掛起;另乙個執行緒使「條件成立」。為了防止競爭,條件變數的使用總是和乙個互斥鎖結合在一起。執行緒在改變條件狀態前必須首先鎖住互斥量,函式pthread_cond_wait把自己放到等待條件的執行緒列表上,然後對互斥鎖解鎖(這兩個操作是原子操作)。在函式返回時,互斥量再次被鎖住。
二。為什麼存在條件變數
首先,舉個例子:在應用程式中有連個執行緒thread1,thread2,thread3和thread4,有乙個int型別的全域性變數icount。icount初始化為0,thread1和thread2的功能是對icount的加1,thread3的功能是對icount的值減1,而thread4的功能是當icount的值大於等於100時,列印提示資訊並重置icount=0。
如果使用互斥量,執行緒**大概應是下面的樣子:
thread1/2:
while (1)
thread4:
while(1)
else
}在上面**中由於thread4並不知道什麼時候icount會大於等於100,所以就會一直在迴圈判斷,但是每次判斷都要加鎖、解鎖(即使本次並沒有修改icount)。這就帶來了問題一,cpu浪費嚴重。所以在**中新增了sleep(),這樣讓每次判斷都休眠一定時間。但這由帶來的第二個問題,如果sleep()的時間比較長,導致thread4處理不夠及時,等icount到了很大的值時才重置。對於上面的兩個問題,可以使用條件變數來解決。
首先看一下使用條件變數後,執行緒**大概的樣子:
thread1/2:
while(1)
}
thread4:
while (1)
printf("icount >= 100\r\n");
icount = 0;
pthread_mutex_unlock(&mutex);
}從上面的**可以看出thread4中,當icount < 100時,會呼叫pthread_cond_wait。而pthread_cond_wait在上面應經講到它會釋放mutex,然後等待條件變為真返回。當返回時會再次鎖住mutex。因為pthread_cond_wait會等待,從而不用一直的輪詢,減少cpu的浪費。在thread1和thread2中的函式pthread_cond_signal會喚醒等待cond的執行緒(即thread4),這樣當icount一到大於等於100就會去喚醒thread4。從而不致出現icount很大了,thread4才去處理。
需要注意的一點是在thread4中使用的while (icount < 100),而不是if (icount < 100)。這是因為在pthread_cond_singal()和pthread_cond_wait()返回之間有時間差,假如在時間差內,thread3又將icount減到了100以下了,那麼thread4就需要在等待條件為真了。
有了互斥量為什麼還要條件變數?
互斥量已經可以保證執行緒的同步,那為什麼還要弄條件變數?用 來測試下 include include include include using namespace std queuemsgs mutex m condition variable cond long long loops 0 voi...
為什麼有了IP位址還需要MAC位址?
長話短說,理由有三點。二.分層實現如果在ip包頭 header 中增加了 下一跳ip位址 這個字段,在邏輯上來說,如果ip位址夠用,交換機也支援根據ip位址 現在的二層交換機不支援這樣做 其實mac位址並不是必要的。但用mac位址和ip位址兩個位址,用於分別表示實體地址和邏輯位址是有好處的。這樣分層...
既然有了HBase,為什麼還需要Kudu呢?
那既然有了hbase,為什麼還需要kudu呢?簡單的說,就是嫌棄hbase在olap 聯機分析處理 場合,sql mr類的批量檢索場景中,效能不夠好。通常這種海量資料olap場景,要不走預處理的路,比如像ebay麒麟這樣走cube管理的,或者像谷歌mesa這樣按業務需求走預定義聚合操作。再有就是自己...