天天看點

線程管理---互斥量同步機制

互斥量機制

在計算機系統中有許多共享資源不允許使用者并行使用,

像列印機這樣的共享裝置被稱為“排它性資源”,

因為它一次隻能由一個執行流通路。執行流必須以互斥的方式

執行通路排它性資源的代碼。

互斥量(Mutex),又稱為互斥鎖,是一種用來保護臨界區的特殊變量,

它可以處于鎖定(locked)狀态,也可以處于解鎖(unlocked)狀态:

 如果互斥鎖是鎖定的,就是一個特定的線程持有這個互斥鎖:

 如果沒有線程持有這個互斥鎖,那麼這個互斥鎖就處于解鎖狀态。

  //互斥量是最簡單也是最有效的線程同步機制。程式可以用它來保護臨界區,

  //以獲得對排它性資源的獨占通路權。另外,互斥量隻能被短時間地持有,

  //使用完臨界資源後應立即釋放鎖。 

    1.互斥量的操作(程式設計操作)

 1.1:建立互斥量,并初始化

 (1).靜态初始化

       對是靜态配置設定的 pthread_mutex_t 變量來說值需要将

  PTHREAD_MUTEX_INITIALIZER賦給變量就行了。

//eg: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

(2).動态初始化

       對動态配置設定或者不使用預設互斥屬性的互斥變量來說,需要

  調用 pthread_mutex_int()函數來執行初始化工作。

//eg:int pthread_mutex_init(pthread_mutex_t *restrict mutex,

//                     const pthread_mutexattr_t *restrict attr);

參數: 

@mutex   是一個指向要初始化的互斥量的指針 

@attr    傳遞 NULL 來初始化一個帶有“預設屬性”的互斥量,否則就要用類似于

         線程屬性對象所使用的方法,先建立互斥量屬性對象,再用該屬性對象來

         建立互斥量。

傳回值:

成功 傳回 0,失敗 傳回一個錯誤碼

        2.2銷毀互斥量

            銷毀互斥量使用 pthread_mutex_destroy()函數,原型如下:

            int pthread_mutex_destroy(pthread_mutex_t *mutex);

            //@ mutex 指向要銷毀的互斥量的指針。

        2.3加鎖與解鎖

2.3.1線程試圖鎖定互斥量的過程稱之為加鎖。

Pthreads 中有兩個試圖鎖定互斥量的函數,

pthread_mutex_lock()和 pthread_mutex_ trylock()。

pthread_mutex_lock()函數會一直阻塞到互斥量可用為止,

而 pthread_mutex_trylock() 會嘗試加鎖,通常立即傳回。函數原型如下:

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex); 

       @ mutex 是需要加鎖的互斥量。

       傳回值:

       成功 傳回 0,

       失敗 傳回錯誤碼,

注:如果,一個線程己持有鎖的情況下,調用 pthread_mutex_trylock()函數錯誤碼為 EBUSY。

        2.3.2解鎖是線程将互斥量由鎖定狀态變為解鎖狀态。

pthread_mutex_unlock()函數用來釋放指定的互斥量。函數原型如下:

int pthread_mutex_unlock(pthread_mutex_t *mutex);

  //線程需要進入臨界區之前正确地擷取适當的互斥量,并線上程離開臨界區時釋放互斥量。

 程式示例 :

該程式使用互斥量來保證多線程同時輸出順序例子,互斥量保證擷取的

線程列印完才讓别的線程列印,杜絕了列印亂序的問題。

1 #include<stdio.h>
2 #include<string.h>
3 #include<pthread.h>
4 #include<stdlib.h>
5 #include<unistd.h>
6 
7 pthread_t tid[2];        //定義線程名
8 pthread_mutex_t lock;   //定義互斥鎖變量
9 
10 void* doPrint(void *arg)  //線程執行函數
11 {
12     int id = (long)arg;
13     int i = 0;
14     pthread_mutex_lock(&lock);	// 使用互斥量保護臨界區	,加鎖
15     printf("Job %d started\n", id);
16     for (i = 0; i < 5; i++) {
17         printf("Job %d printing\n", id);
18         usleep(10);
19     }
20     printf("Job %d finished\n", id);
21     pthread_mutex_unlock(&lock);                         //解鎖
22     return NULL;
23 }
24 
25 int main(void)
26 {
27     long i = 0;
28     int err;
29 
30     if (pthread_mutex_init(&lock, NULL) != 0) /* 動态初始化互斥量*/
	   {
31         printf("\n Mutex init failed\n");
32         return 1;
33     }
34     while (i < 2) 
	   {
35         err = pthread_create(&(tid[i]), NULL, &doPrint, (void*)i);
36         if (err != 0)
37         printf("Can't create thread :[%s]", strerror(err));
38         i++;
39     }
40     pthread_join(tid[0], NULL);
41     pthread_join(tid[1], NULL);
42     pthread_mutex_destroy(&lock); //銷毀互斥量
43 
44     return 0;
45 }