[cpp] view plaincopy 互斥量(mutex)從本質上說是一把鎖,在訪問共享資源前對互斥量進行加鎖,在訪問完成后釋放互斥量上的鎖。對互斥量進行加鎖以后,任何其他試圖再次對互斥鎖加鎖的線程將會阻塞直到當前線程釋放該互斥鎖。如果釋放互斥鎖時有多個線程阻塞,所有在該互斥鎖上的阻塞線程都會變成可運行狀態(tài),第一個變?yōu)檫\行狀態(tài)的線程可以對互斥鎖加鎖,其他線程將會看到互斥鎖依然被鎖住,只能回去再次等待它重新變?yōu)榭捎谩?/p> 條件變量(cond)是在多線程程序中用來實現(xiàn)"等待--》喚醒"邏輯常用的方法。條件變量利用線程間共享的全局變量進行同步的一種機制,主要包括兩個動作:一個線程等待"條件變量的條件成立"而掛起;另一個線程使“條件成立”。為了防止競爭,條件變量的使用總是和一個互斥鎖結合在一起。線程在改變條件狀態(tài)前必須首先鎖住互斥量,函數(shù)pthread_cond_wait把自己放到等待條件的線程列表上,然后對互斥鎖解鎖(這兩個操作是原子操作)。在函數(shù)返回時,互斥量再次被鎖住。
二。為什么存在條件變量 首先,舉個例子:在應用程序中有連個線程thread1,thread2,thread3和thread4,有一個int類型的全局變量iCount。iCount初始化為0,thread1和thread2的功能是對iCount的加1,thread3的功能是對iCount的值減1,而thread4的功能是當iCount的值大于等于100時,打印提示信息并重置iCount=0。 如果使用互斥量,線程代碼大概應是下面的樣子: thread1/2: while (1) { pthread_mutex_lock(&mutex); iCount++; pthread_mutex_unlock(&mutex); } thread4: while(1) { pthead_mutex_lock(&mutex); if (100 <= iCount) { printf("iCount >= 100\r\n"); iCount = 0; pthread_mutex_unlock(&mutex); } else { pthread_mutex_unlock(&mutex); } } 在上面代碼中由于thread4并不知道什么時候iCount會大于等于100,所以就會一直在循環(huán)判斷,但是每次判斷都要加鎖、解鎖(即使本次并沒有修改iCount)。這就帶來了問題一,CPU浪費嚴重。所以在代碼中添加了sleep(),這樣讓每次判斷都休眠一定時間。但這由帶來的第二個問題,如果sleep()的時間比較長,導致thread4處理不夠及時,等iCount到了很大的值時才重置。對于上面的兩個問題,可以使用條件變量來解決。首先看一下使用條件變量后,線程代碼大概的樣子: thread1/2: while(1) { pthread_mutex_lock(&mutex); iCount++; pthread_mutex_unlock(&mutex); if (iCount >= 100) { pthread_cond_signal(&cond); } } thread4: while (1) { pthread_mutex_lock(&mutex); while(iCount < 100) { pthread_cond_wait(&cond, &mutex); } printf("iCount >= 100\r\n"); iCount = 0; pthread_mutex_unlock(&mutex); } 從上面的代碼可以看出thread4中,當iCount < 100時,會調用pthread_cond_wait。而pthread_cond_wait在上面應經講到它會釋放mutex,然后等待條件變?yōu)檎娣祷?。當返回時會再次鎖住mutex。因為pthread_cond_wait會等待,從而不用一直的輪詢,減少CPU的浪費。在thread1和thread2中的函數(shù)pthread_cond_signal會喚醒等待cond的線程(即thread4),這樣當iCount一到大于等于100就會去喚醒thread4。從而不致出現(xiàn)iCount很大了,thread4才去處理。 需要注意的一點是在thread4中使用的while (iCount < 100),而不是if (iCount < 100)。這是因為在pthread_cond_singal()和pthread_cond_wait()返回之間有時間差,假如在時間差內,thread3又將iCount減到了100以下了,那么thread4就需要在等待條件為真了。
|
|
來自: astrotycoon > 《thread》