多執行緒(2)-執行緒同步條件變數

lethe1203發表於2024-04-04
在 Linux 多執行緒程式設計中,條件變數是一種用於執行緒間同步的重要機制。它通常與互斥鎖結合使用,用於解決多個執行緒競爭共享資源的問題。條件變數允許一個執行緒在等待某個條件變為真時阻塞,並且在另一個執行緒改變條件並通知時恢復執行。這個玩意跟核心等待佇列差不多意思。
在 Linux 多執行緒程式設計中,使用條件變數進行執行緒同步通常涉及以下幾個相關的函式:
pthread_cond_init: 該函式用於初始化條件變數。
原型為 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)。
引數 cond 是要初始化的條件變數,attr 是條件變數的屬性,通常為 NULL。

pthread_cond_destroy: 用於銷燬條件變數。
原型為 int pthread_cond_destroy(pthread_cond_t *cond)。
引數 cond 是要銷燬的條件變數。

pthread_cond_wait: 該函式用於等待條件變數的狀態發生變化。
原型為 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)。
引數 cond 是要等待的條件變數,mutex 是與條件變數配合使用的互斥鎖。在呼叫該函式時,執行緒會釋放互斥鎖並阻塞,直到條件變數被其他執行緒發出訊號喚醒。

pthread_cond_timedwait: 類似於 pthread_cond_wait,但是可以設定超時時間,防止永久等待。
原型為 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)。

pthread_cond_signal: 該函式用於傳送訊號給等待條件變數的一個執行緒。
原型為 int pthread_cond_signal(pthread_cond_t *cond)。呼叫該函式會喚醒等待佇列中的一個執行緒。

pthread_cond_broadcast: 類似於 pthread_cond_signal,但會喚醒等待佇列中的所有執行緒。
原型為 int pthread_cond_broadcast(pthread_cond_t *cond)。

條件變數demo:

在此demo中,有一個生產者執行緒和一個消費者執行緒,它們共享一個整數變數 shared_data。生產者執行緒週期性地增加 shared_data 的值,而消費者執行緒在 shared_data 不為零時消費一個資料。生產者在生產了一個資料後會傳送訊號通知消費者執行緒,消費者在消費資料時需要先檢查條件是否滿足,如果不滿足,則等待條件變為真。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int shared_data = 0;

void* producer(void* arg) {
    while (1) {
        pthread_mutex_lock(&mutex);
        shared_data++; // 生產一個資料
        printf("Produced: %d\n", shared_data);
        pthread_cond_signal(&cond); // 傳送訊號通知消費者
        pthread_mutex_unlock(&mutex);
        sleep(1); // 生產者休眠1秒
    }
    return NULL;
}

void* consumer(void* arg) {
    while (1) {
        pthread_mutex_lock(&mutex);
        while (shared_data == 0) { // 等待條件變為真
            pthread_cond_wait(&cond, &mutex);
        }
        printf("Consumed: %d\n", shared_data);
        shared_data--; // 消費一個資料
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main() {
    pthread_t producer_thread, consumer_thread;
    pthread_create(&producer_thread, NULL, producer, NULL);
    pthread_create(&consumer_thread, NULL, consumer, NULL);
    pthread_join(producer_thread, NULL);
    pthread_join(consumer_thread, NULL);
    return 0;
}

條件變數demo執行結果:

0

相關文章