線程同步與互斥——互斥鎖

瀏覽博客時發現一篇博客寫的不錯就轉載了一下,原博客網址:http://blog.csdn.net/tennysonsky/article/details/46494077

爲何須要互斥鎖?

在多任務操做系統中,同時運行的多個任務可能都須要使用同一種資源。這個過程有點相似於,公司部門裏,我在使用着打印機打印東西的同時(尚未打印完),別人恰好也在此刻使用打印機打印東西,若是不作任何處理的話,打印出來的東西確定是錯亂的。ide


下面咱們用程序模擬一下這個過程,線程一須要打印「 hello 」,線程二須要打印「 world 」,不加任何處理的話,打印出來的內容會錯亂:函數

[cpp] view plain copyurl

  1. #include <stdio.h>  spa

  2. #include <pthread.h>  操作系統

  3. #include <unistd.h>  .net

  4.   

  5. // 打印機  線程

  6. void printer(char *str)  orm

  7. {  blog

  8.     while(*str!='\0')  ip

  9.     {  

  10.         putchar(*str);    

  11.         fflush(stdout);  

  12.         str++;  

  13.         sleep(1);  

  14.     }  

  15.     printf("\n");   

  16. }  

  17.   

  18. // 線程一  

  19. void *thread_fun_1(void *arg)  

  20. {  

  21.     char *str = "hello";  

  22.     printer(str); //打印  

  23. }  

  24.   

  25. // 線程二  

  26. void *thread_fun_2(void *arg)  

  27. {  

  28.     char *str = "world";  

  29.     printer(str); //打印  

  30. }  

  31.   

  32. int main(void)  

  33. {  

  34.     pthread_t tid1, tid2;  

  35.       

  36.     // 建立 2 個線程  

  37.     pthread_create(&tid1, NULL, thread_fun_1, NULL);  

  38.     pthread_create(&tid2, NULL, thread_fun_2, NULL);  

  39.   

  40.     // 等待線程結束,回收其資源  

  41.     pthread_join(tid1, NULL);  

  42.     pthread_join(tid2, NULL);   

  43.       

  44.     return 0;  

  45. }  


運行結果以下:




實際上,打印機是有作處理的,我在打印着的時候別人是不容許打印的,只有等我打印結束後別人才容許打印。這個過程有點相似於,把打印機放在一個房間裏,給這個房間安把鎖,這個鎖默認是打開的。當 A 須要打印時,他先過來檢查這把鎖有沒有鎖着,沒有的話就進去,同時上鎖在房間裏打印。而在這時,恰好 B 也須要打印,B 一樣先檢查鎖,發現鎖是鎖住的,他就在門外等着。而當 A 打印結束後,他會開鎖出來,這時候 B 才進去上鎖打印。


而在線程裏也有這麼一把鎖——互斥鎖(mutex),互斥鎖是一種簡單的加鎖的方法來控制對共享資源的訪問,互斥鎖只有兩種狀態,即上鎖( lock )和解鎖( unlock )。


互斥鎖的操做流程以下:

1)在訪問共享資源後臨界區域前,對互斥鎖進行加鎖。

2)在訪問完成後釋放互斥鎖導上的鎖。

3)對互斥鎖進行加鎖後,任何其餘試圖再次對互斥鎖加鎖的線程將會被阻塞,直到鎖被釋放。


互斥鎖的數據類型是: pthread_mutex_t


互斥鎖基本操做


如下函數須要的頭文件:

#include <pthread.h>


1)初始化互斥鎖

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

功能:

初始化一個互斥鎖。

參數:

mutex:互斥鎖地址。類型是 pthread_mutex_t 。
attr:設置互斥量的屬性,一般可採用默認屬性,便可將 attr 設爲 NULL。


可使用宏 PTHREAD_MUTEX_INITIALIZER 靜態初始化互斥鎖,好比:
pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
這種方法等價於使用 NULL 指定的 attr 參數調用  pthread_mutex_init () 來完成動態初始化,不一樣之處在於  PTHREAD_MUTEX_INITIALIZER  宏不進行錯誤檢查。

返回值:

成功:0,成功申請的鎖默認是打開的。

失敗:非 0 錯誤碼


2)上鎖

int pthread_mutex_lock(pthread_mutex_t *mutex);

功能:

對互斥鎖上鎖,若互斥鎖已經上鎖,則調用者一直阻塞,直到互斥鎖解鎖後再上鎖。

參數:

mutex:互斥鎖地址。

返回值:

成功:0

失敗:非 0 錯誤碼


int pthread_mutex_trylock(pthread_mutex_t *mutex);

調用該函數時,若互斥鎖未加鎖,則上鎖,返回 0;若互斥鎖已加鎖,則函數直接返回失敗,即 EBUSY。


3)解鎖

int pthread_mutex_unlock(pthread_mutex_t * mutex);

功能:

對指定的互斥鎖解鎖。

參數:

mutex:互斥鎖地址。

返回值:

成功:0

失敗:非 0 錯誤碼


4)銷燬互斥鎖

int pthread_mutex_destroy(pthread_mutex_t *mutex);

功能:

銷燬指定的一個互斥鎖。互斥鎖在使用完畢後,必需要對互斥鎖進行銷燬,以釋放資源。

參數:

mutex:互斥鎖地址。

返回值:

成功:0

失敗:非 0 錯誤碼


互斥鎖應用實例

咱們經過互斥鎖完善上面的例子,示例代碼以下:

[cpp] view plain copy

  1. #include <stdio.h>  

  2. #include <pthread.h>  

  3. #include <unistd.h>  

  4.   

  5. pthread_mutex_t mutex; //互斥鎖  

  6.   

  7. // 打印機  

  8. void printer(char *str)  

  9. {  

  10.     pthread_mutex_lock(&mutex); //上鎖  

  11.     while(*str!='\0')  

  12.     {  

  13.         putchar(*str);    

  14.         fflush(stdout);  

  15.         str++;  

  16.         sleep(1);  

  17.     }  

  18.     printf("\n");   

  19.     pthread_mutex_unlock(&mutex); //解鎖  

  20. }  

  21.   

  22. // 線程一  

  23. void *thread_fun_1(void *arg)  

  24. {  

  25.     char *str = "hello";  

  26.     printer(str); //打印  

  27. }  

  28.   

  29. // 線程二  

  30. void *thread_fun_2(void *arg)  

  31. {  

  32.     char *str = "world";  

  33.     printer(str); //打印  

  34. }  

  35.   

  36. int main(void)  

  37. {  

  38.     pthread_t tid1, tid2;  

  39.       

  40.     pthread_mutex_init(&mutex, NULL); //初始化互斥鎖  

  41.       

  42.     // 建立 2 個線程  

  43.     pthread_create(&tid1, NULL, thread_fun_1, NULL);  

  44.     pthread_create(&tid2, NULL, thread_fun_2, NULL);  

  45.   

  46.     // 等待線程結束,回收其資源  

  47.     pthread_join(tid1, NULL);  

  48.     pthread_join(tid2, NULL);   

  49.       

  50.     pthread_mutex_destroy(&mutex); //銷燬互斥鎖  

  51.       

  52.     return 0;  

  53. }  



運行結果以下:


相關文章
相關標籤/搜索