Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 線程同步:互斥量 詳細指南與實戰

編輯:Linux 教學

什麼是互斥量

互斥量是多線程編程中實現同步訪問的核心機制,它允許程式鎖定特定代碼段或共享資源,確保同一時刻僅有一個線程能夠訪問。本質上,互斥量與信號量同屬 P/V 操作體系:進入臨界區前加鎖(P 操作),退出後解鎖(V 操作)。

核心 API 速查

函數功能返回值
pthread_mutex_init()初始化互斥量成功返回 0,失敗返回錯誤碼(不設 errno)
pthread_mutex_lock()加鎖(阻塞等待)同上
pthread_mutex_trylock()非阻塞嘗試加鎖同上,鎖已被佔用時立即返回 EBUSY
pthread_mutex_unlock()解鎖同上
pthread_mutex_destroy()銷毀互斥量同上

實戰案例:主線程輸入、子線程轉大寫

需求:主線程持續從標準輸入讀取字符串,輸入 "end" 終止;子線程將輸入轉為大寫並輸出。使用互斥量保護共享緩衝區,信號量協調線程切換。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

void *threadFunc(void *arg);
pthread_mutex_t work_mutex;
sem_t sem;

#define WORK_SIZE 1024
char work_area[WORK_SIZE];

int main() {
    int res;
    pthread_t thread1;
    void *threadRes;

    // 初始化互斥量
    res = pthread_mutex_init(&work_mutex, NULL);
    if (res != 0) { perror("Mutex init failed"); exit(EXIT_FAILURE); }

    // 初始化信號量(初值 0)
    res = sem_init(&sem, 0, 0);
    if (res != 0) { perror("Semaphore init failed"); exit(EXIT_FAILURE); }

    // 創建子線程
    res = pthread_create(&thread1, NULL, threadFunc, NULL);
    if (res != 0) { perror("Thread create failed"); exit(EXIT_FAILURE); }

    printf("Input some text. Enter 'end' to finish.\n");
    pthread_mutex_lock(&work_mutex);
    while (strncmp(work_area, "end", 3) != 0) {
        fgets(work_area, WORK_SIZE, stdin);
        pthread_mutex_unlock(&work_mutex);
        sem_wait(&sem); // 等待子線程處理完畢

        pthread_mutex_lock(&work_mutex);
    }
    pthread_mutex_unlock(&work_mutex);

    printf("\nWaiting for thread to finish...\n");
    res = pthread_join(thread1, &threadRes);
    if (res != 0) { perror("Thread join failed"); exit(EXIT_FAILURE); }

    printf("Thread joined.\n");
    pthread_mutex_destroy(&work_mutex);
    sem_destroy(&sem);
    exit(EXIT_SUCCESS);
}

void *threadFunc(void *arg) {
    pthread_mutex_lock(&work_mutex);
    while (strncmp(work_area, "end", 3) != 0) {
        if (work_area[0] != '\0') {
            for (int i = 0; work_area[i] != '\0'; ++i) {
                if (work_area[i] >= 'a' && work_area[i] <= 'z')
                    work_area[i] -= 'a' - 'A';
            }
            printf("After converted: %s\n", work_area);
            sem_post(&sem); // 通知主線程可繼續讀取
            memset(work_area, 0, sizeof(work_area));
        }
        pthread_mutex_unlock(&work_mutex);
        sleep(1);
        pthread_mutex_lock(&work_mutex);
    }
    pthread_mutex_unlock(&work_mutex);
    sem_post(&sem);
    pthread_exit(NULL);
}

關鍵點與避坑指南

  • 鎖的粒度:僅保護共享緩衝區讀寫,避免長時間持有鎖(如 sleep() 在鎖外)。
  • 信號量配合:互斥量保護數據,信號量同步步驟,二者分工明確。
  • 死鎖風險:多鎖時需固定加鎖順序;本例僅單一互斥量,風較低。
  • 邊界條件:strncmp 比較 "end" 需確保緩衝區以空字符結尾,fgets 保留換行符,實際項目中需去除。

多線程同步之難,在於人腦天然單線程思維,需通過大量實踐建立並發直覺。「左手畫圓右手畫方」的協調,唯有多思、多寫、多填坑方能精進。

Copyright © Windows教程網 All Rights Reserved