Linux C進程與多線程入門—(5)使用互斥量進行同步

本文出自https://shuwoom.com博客,歡迎訪問!

互斥

簡單地理解就是,一個線程進入工作區後,如果有其他線程想要進入工作區,它就會進入等待狀態,要等待工作區內的線程結束後纔可以進入。

 

基本函數

(1)  pthread_mutex_init函數

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

描述:設置互斥量的屬性

參數:第一個參數:預先聲明的pthread_mutex_t對象指針

          第二個參數:互斥鎖屬性,NULL表示使用默認屬性

返回值:成功時返回0, 失敗時返回一個錯誤代碼

 

(2) pthread_mutex_lock函數

原型:int pthread_mutex_lock ( pthread_mutex_t *mutex );

描述:pthread_mutex_lock返回時,互斥鎖被鎖定,如果這個互斥鎖被一個線程鎖定和擁有,那麼另一個線程要調用這        個函數會進入堵塞狀態(即等待狀態),直到互斥鎖被釋放爲止。

返回值:成功時返回0, 失敗時返回一個錯誤代碼

 

(3) pthread_mutex_unlock函數

原型:int pthread_mutex_unlock ( pthread_mutex_t *mutex );

描述:釋放互斥鎖

返回值:成功時返回0, 失敗時返回一個錯誤代碼

 

(4) pthread_mutex_destroy函數

原型:int pthread_mutex_destroy ( pthread_mutex_t *mutex );

描述:刪除互斥鎖

返回值:成功時返回0, 失敗時返回一個錯誤代碼

 

 

實例

lock.c文件

描述:這個程序主要可以概括爲主線程負責接受輸入的字符串,而子線程則負責統計並輸出字符數。

 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
void *thread_function(void *arg);
pthread_mutex_t work_mutex;  
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit = 0;
int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;
    /*初始化互斥量*/
    res = pthread_mutex_init(&work_mutex, NULL);
    if (res != 0) {
        perror("互斥量初始化失敗!");
        exit(EXIT_FAILURE);
    }
    /*啓動新線程*/
    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("線程創建失敗");
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&work_mutex);
    printf("請輸入一些文本內容. 輸入“end”結束\n");
    while(!time_to_exit) {
        fgets(work_area, WORK_SIZE, stdin);
        pthread_mutex_unlock(&work_mutex);
        while(1) {
            pthread_mutex_lock(&work_mutex);
            /*統計字符工作未完成*/
            if (work_area[0] != '\0') {
                pthread_mutex_unlock(&work_mutex);
                sleep(1);
            }
            else {
                /*統計字符工作完成,跳出內層循環,重新讀取輸入*/
                break;
            }
        }
    }
    pthread_mutex_unlock(&work_mutex);
    printf("\n等待線程結束...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
    pthread_mutex_destroy(&work_mutex);
    exit(EXIT_SUCCESS);
}
/*主線程首先鎖定工作區,在獲取輸入的字符後,釋放工作區,讓其他線程對字符個數進行統計。work_area[0[爲空字符時表示統計結束。通過週期性地對互斥量進行加鎖,檢查是否已經統計完。*/
/*在線程中要執行的代碼*/
void *thread_function(void *arg) {
    sleep(1);
    pthread_mutex_lock(&work_mutex);
    while(strncmp("end", work_area, 3) != 0) {
        printf("你輸入了 %d 個字符\n", strlen(work_area) -1);
        work_area[0] = '\0';
        pthread_mutex_unlock(&work_mutex);
        sleep(1);
        pthread_mutex_lock(&work_mutex);
      
        while (work_area[0] == '\0' ) {
            pthread_mutex_unlock(&work_mutex);
            sleep(1);
            pthread_mutex_lock(&work_mutex);
        }
    }
    time_to_exit = 1;
    work_area[0] = '\0';
    pthread_mutex_unlock(&work_mutex);
    pthread_exit(0);
}

 

/*在新線程一上來先試圖對互斥量進行加鎖。如果它已經被鎖上,新線程就會進入堵塞狀態知道互斥鎖釋放爲止,

一旦可以進入工作區,就先檢查是否有退出請求(end)如果有,就設置time_to_exit變量和work_area,然後退出程序。

如果沒有退出,那麼就對字符個數進行統計。把work_area[0]設置爲空,表示統計工作完成。接下來就釋放互斥鎖,

等待主線程的運行,週期性地給互斥量加鎖,如果加鎖成功,就檢查主線程是否又給我們新的字符串統計。如果沒有,

就釋放互斥鎖繼續等待,*/

 

 

 

 

 

 

 

編譯執行:gcc -D_REENTRANT fork.c -o fork -lpthread

運行結果如下:

 

 

參考文獻:Linux程序設計

 

 

發佈了66 篇原創文章 · 獲贊 82 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章