Linux 多任務編程——線程同步與互斥:互斥鎖

爲什麼需要互斥鎖?
在多任務操作系統中,同時運行的多個任務可能都需要使用同一種資源。這個過程有點類似於,公司部門裏,我在使用着打印機打印東西的同時(還沒有打印完),別人剛好也在此刻使用打印機打印東西,如果不做任何處理的話,打印出來的東西肯定是錯亂的。

下面我們用程序模擬一下這個過程,線程一需要打印“ hello ”,線程二需要打印“ world ”,不加任何處理的話,打印出來的內容會錯亂:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
 
// 打印機
void printer(char *str)
{
    while(*str!='\0')
    {
        putchar(*str);    
        fflush(stdout);
        str++;
        sleep(1);
    }
    printf("\n"); 
}
 
// 線程一
void *thread_fun_1(void *arg)
{
    char *str = "hello";
    printer(str); //打印
}
 
// 線程二
void *thread_fun_2(void *arg)
{
    char *str = "world";
    printer(str); //打印
}
 
int main(void)
{
    pthread_t tid1, tid2;
    
    // 創建 2 個線程
    pthread_create(&tid1, NULL, thread_fun_1, NULL);
    pthread_create(&tid2, NULL, thread_fun_2, NULL);
 
    // 等待線程結束,回收其資源
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL); 
    
    return 0;
}

運行結果如下:


實際上,打印機是有做處理的,我在打印着的時候別人是不允許打印的,只有等我打印結束後別人才允許打印。這個過程有點類似於,把打印機放在一個房間裏,給這個房間安把鎖,這個鎖默認是打開的。當 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。

返回值:

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

失敗:非 0 錯誤碼

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

 

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 錯誤碼

 

互斥鎖應用實例

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
 
pthread_mutex_t mutex; //互斥鎖
 
// 打印機
void printer(char *str)
{
    pthread_mutex_lock(&mutex); //上鎖
    while(*str!='\0')
    {
        putchar(*str);    
        fflush(stdout);
        str++;
        sleep(1);
    }
    printf("\n"); 
    pthread_mutex_unlock(&mutex); //解鎖
}
 
// 線程一
void *thread_fun_1(void *arg)
{
    char *str = "hello";
    printer(str); //打印
}
 
// 線程二
void *thread_fun_2(void *arg)
{
    char *str = "world";
    printer(str); //打印
}
 
int main(void)
{
    pthread_t tid1, tid2;
    
    pthread_mutex_init(&mutex, NULL); //初始化互斥鎖
    
    // 創建 2 個線程
    pthread_create(&tid1, NULL, thread_fun_1, NULL);
    pthread_create(&tid2, NULL, thread_fun_2, NULL);
 
    // 等待線程結束,回收其資源
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL); 
    
    pthread_mutex_destroy(&mutex); //銷燬互斥鎖
    
    return 0;
}

運行結果如下:

 

--------------------- 
作者:Mike__Jiang 
來源:CSDN 
原文:https://blog.csdn.net/tennysonsky/article/details/46494077 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章