下面以乙個簡單的多執行緒程式來演示如何使用互斥量來進行執行緒同步。在主線程中,我們建立子執行緒,並把陣列msg作為引數傳遞給子執行緒,然後主線程呼叫函式pthread_mutex_lock對互斥量加鎖,等待輸入,輸入完成後,呼叫函式pthread_mutex_unlock對互斥量解鎖,從而使執行緒函式中的對互斥量加鎖的pthread_mutex_lock函式返回並執行子執行緒中的**。執行緒函式在把字串的小寫字母變成大寫並統計輸入的字元數量之後,它呼叫pthread_mutex_unlock對互斥量解鎖,使主線程能夠繼續獲得互斥量(即對其加鎖函式返回),再次執行輸入功能直到主線程再次呼叫pthread_mutex_unlock對其解鎖,一直如此重複,直到輸入end。
執行結果如下:
#include #include #include #include #include //宣告執行緒函式和互斥量
void* thread_func(void *msg);
pthread_mutex_t mutex;
#define msg_size 512
int main()
; //初始化互斥量,使用預設的互斥量屬性
res = pthread_mutex_init(&mutex, null);
if(res != 0)
//建立子執行緒,並把msg作為執行緒函式的引數傳遞給thread_func
res = pthread_create(&thread, null, thread_func, msg);
if(res != 0)
//輸入字串,以串『end』結束
printf("input some test. enter 'end' to finish\n");
//把互斥量mutex加鎖,以確保同一時間只有該執行緒可以訪問msg中的資料
pthread_mutex_lock(&mutex);
while(strcmp("end\n", msg) != 0)
else
//把互斥量mutex解鎖,讓其他的執行緒可以訪問msg中的資料
pthread_mutex_unlock(&mutex);
sleep(1);//休眠1秒再繼續迴圈,讓其他執行緒有執行的機會
pthread_mutex_lock(&mutex);
} pthread_mutex_unlock(&mutex);
printf("\nwaiting for thread finish...\n");
//等待子執行緒結束
res = pthread_join(thread, &thread_result);
if(res != 0)
printf("thread joined\n");
//清理互斥量
pthread_mutex_destroy(&mutex);
exit(exit_success);
}void* thread_func(void *msg)
} printf("you input %d characters\n", i-1);
printf("to uppercase: %s\n", ptr);
//把互斥量mutex解鎖,讓其他的執行緒可以訪問msg中的資料
pthread_mutex_unlock(&mutex);
sleep(1);//休眠1秒再繼續迴圈,讓其他執行緒有執行的機會
pthread_mutex_lock(&mutex);
} pthread_mutex_unlock(&mutex);
//退出執行緒
程式分析:
這個程式的工作流程已經說得非常清楚了,這裡先來說說在main函式和執行緒函式thread_func中while迴圈中的sleep(1)語句的作用。可能很多人會認為這個sleep(1)是為了讓子執行緒完成其處理和統計功能,所以要讓主線程休眠1秒鐘來等待子執行緒的處理統計工作的完成。的確在這裡子執行緒進行的工作十分簡單,1秒鐘內的確可以處理統計完畢。但是這裡的sleep(1)並不是為了實現這個功能,這兩個迴圈中的sleep(1)是為了讓其他的執行緒有機會被執行到,如果在一次的加鎖和解鎖之間沒有這條語句的話,則當前的執行緒將會一直在迴圈中獲得互斥量,因為其他的執行緒沒有執行它的**的時間,所以就要用這樣的一條語句來給其他的執行緒乙個執行的機會。如果子執行緒的執行時間超過1秒,這個程式還是會正常執行。
以這個例子來說,在主線程中,當輸入資料完畢並對互斥量解鎖之後,並不馬上迴圈對其加鎖,此時子執行緒就有了執行的機會,它會對互斥量進行加鎖,同樣地,當它處理統計完輸入的資料後,它在進入下一次迴圈前,也休眠1秒,讓主線程有機會再次執行。而主線程什麼時候能夠執行,取決於子執行緒何時對互斥量進行解鎖。因為如果子執行緒擁有(鎖住)互斥量,則主線程中函式pthread_mutex_lock就不會返回,使主線程處於阻塞狀態。
換句話來說,就是
只有子執行緒結束了對輸入的處理和統計後,主線程才能繼續執行,向msg中寫入資料。看到這裡,你應該知道之前在使用訊號量時,我們多用乙個訊號量也是為了達到這個目的。所以當我們輸入test時,程式有兩個輸入,但還是能正常執行,同樣解決了之前使用乙個訊號量時所帶來的問題。
訊號量和互斥量的作用都是保護**段的互斥裝置,它們也非常相似。但在本例中,與使用訊號量相比,實現同樣的功能,如果使用訊號量的話,則需要兩個訊號量,而使用互斥量的話,只需要乙個。可以說在本例中,使用互斥量更簡單。但是我覺得使用互斥量更容易犯錯,我們可以看到在這個例子中,我們需要使用sleep語句來讓其他執行緒獲得執行的機會,但是在使用訊號量的程式,它並不需要使用sleep,相對來說比較直觀。我知道可能是我的實現方法不好,但是對於使用互斥量來說,我想了很久也想不到不使用sleep的方法。
執行緒同步 互斥量
互斥量的使用 執行緒同步之互斥量 include include include include include include include using namespace std 全域性變數,兩個執行緒都可以修改,因此修改的時候需要加鎖 int g value 0 互斥量 pthread mu...
執行緒同步(互斥量)
原理 建立與銷毀 include int pthread mutex init pthread mutex t restrict mutex,const pthread mutexattr t restrict attr int pthread mutex destroy pthread mutex...
執行緒同步 使用互斥量
1.初始化與銷毀互斥量 linux使用pthread mutex t 資料型別表示互斥量,並使用pthread mutex init函式對互斥量進行初始化。include int pthread mutex init pthread mutex t restrict mutex,const pthr...