GCond


在執行緒的同步化時,有些條件下執行緒必須等待,有些條件下則不用,這可以使用GCond來達到。

例如在生產者(Producer)與消費者(Consumer)的例子中,如果生產者會將產品交到倉庫,而消費者從倉庫取走產品,倉庫一次只能持有固定數量產品,如果生產者生產了過多的產品,倉庫叫生產者等一下 (wait),如倉庫中有空位放產品了再發信號(signal)通知生產者繼續生產,如果倉庫中沒有產品了,倉庫會告訴消費者等一下(wait),如果倉庫中有產品 了再發信號(signal)通知消費者來取走產品。

以下舉一個最簡單的:生產者每次生產一個int整數交至倉庫,而消費者從倉庫取走整數,倉庫一次只能持有一個整數,以程式實例來看:
  • gcond_demo.c
#include <glib.h>

GMutex *mutex = NULL;
GCond* cond = NULL;
int storage = -1;

gboolean producer_thread_end = FALSE;
gboolean consumer_thread_end = FALSE;

// 生產者透過此函式設定產品
void produce_product(int product) {
g_mutex_trylock(mutex);

if(storage != -1) {
// 目前沒有空間收產品,請稍候!
g_cond_wait(cond, mutex);
}

storage = product;
g_print("生產者設定 %d\n", storage);

// 喚醒消費者可以繼續工作了
g_cond_signal(cond);

g_mutex_unlock(mutex);
}

// 消費者透過此函式取走產品
int consume_product() {
g_mutex_trylock(mutex);

if(storage == -1) {
// 缺貨了,請稍候!
g_cond_wait(cond, mutex);
}

int p = storage;
g_print("消費者取走 %d\n", storage);

storage = -1;

// 喚醒生產者可以繼續工作了
g_cond_signal(cond);

g_mutex_unlock(mutex);

return p;
}

// 生產者執行緒會執行此函式
gpointer producer_thread(gpointer data) {
int i;
for(i = 1; i <= 10; i++) {
g_usleep(rand());
produce_product(i);
}
producer_thread_end = TRUE;
}

// 消費者執行緒會執行此函式
gpointer consumer_thread(gpointer data) {
int i;
for(i = 1; i <= 10; i++) {
g_usleep(rand());
consume_product();
}
consumer_thread_end = TRUE;
}

gpointer checking_thread(gpointer mloop) {
while(TRUE) {
if(producer_thread_end && consumer_thread_end) {
g_main_loop_quit(mloop);
break;
}
g_usleep(1000);
}
}

int main(int argc, char *argv[]) {
GMainLoop *mloop;

if(!g_thread_supported()) {
g_thread_init(NULL);
}

mloop = g_main_loop_new(NULL, FALSE);

mutex = g_mutex_new();
cond = g_cond_new();

g_thread_create(producer_thread, NULL, FALSE, NULL);
g_thread_create(consumer_thread, NULL, FALSE, NULL);
g_thread_create(checking_thread, mloop, FALSE, NULL);

g_main_loop_run(mloop);

return 0;
}

執行結果:
生產者設定 1
消費者取走 1
生產者設定 2
消費者取走 2
生產者設定 3
消費者取走 3
生產者設定 4
消費者取走 4
生產者設定 5
消費者取走 5
生產者設定 6
消費者取走 6
生產者設定 7
消費者取走 7
生產者設定 8
消費者取走 8
生產者設定 9
消費者取走 9
生產者設定 10
消費者取走 10

生產者會生產10個整數,而消費者會消耗10個整數,由於倉庫只能放置一個整數,所以每生產一個就消耗一個,其結果如上所示是無誤的。