執行緒同步 條件變數

2021-07-04 07:26:04 字數 4996 閱讀 5871

1. 問題引入:互斥鎖問題,假設現在有兩個資源a和b,乙個執行緒先拿a再拿b,另乙個則相反,這樣導致的問題就是死鎖,即兩個執行緒無休止的互相等待

#include #include #include #include pthread_mutex_t g_mtxa = pthread_mutex_initializer;

pthread_mutex_t g_mtxb = pthread_mutex_initializer;

void* thread_proc1 (void* arg)

void* thread_proc2 (void* arg)

int main (void)

pthread_t tid2;

if ((error = pthread_create (&tid2, null, thread_proc2,

null)) != 0)

if ((error = pthread_join (tid1, null)) != 0)

if ((error = pthread_join (tid2, null)) != 0)

printf ("大功告成!\n");

思考:解決上面問題的核心就是讓乙個資源同時使用a和b,使用完在釋放,這樣就不會出現互相等待導致死鎖的問題。

2.  條件變數:條件變數是一種同步機制,允許執行緒掛起,直到共享資料上的某些條件得到滿足。條件變數上的基本操作有:觸發條件(當條件變為 true 時);等待條件,掛起執行緒直到其他執行緒觸發條件。條件變數必須和互斥鎖一起使用

int pthread_cond_init (pthread_cond_t* cond,const pthread_condattr_t* attr);// 初始化條件變數

pthread_cond_t cond = pthread_cond_initializer;// 作用和上個函式等價

int pthread_cond_wait (pthread_cond_t* cond,pthread_mutex_t* mutex);// 使呼叫執行緒睡入條件變數cond,同時釋放互斥鎖mutex,

int pthread_cond_timedwait (pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime);// abstime 指定的時間內 cond 未觸發,互斥量 mutex 被重新加鎖

struct timespec ;

int pthread_cond_signal (pthread_cond_t* cond);// 從條件變數cond中喚出乙個執行緒, 令其重新獲得原先的互斥鎖

注意:被喚出的執行緒此刻將從pthread_cond_wait函式中返回,但如果該執行緒無法獲得原先的鎖,則會繼續阻塞在加鎖上。

int pthread_cond_broadcast (pthread_cond_t* cond);// 從條件變數cond中喚出所有執行緒
int pthread_cond_destroy (pthread_cond_t* cond);//銷毀條件變數釋放資源
3. 生產者消費者模型:兩個生產 者生產a-z的字元,兩個消費者執行緒

#include #include #include #include #include #define max_stock 20 // 倉庫容量

char g_storage[max_stock]; // 倉庫

size_t g_stock = 0; // 當前庫存

pthread_mutex_t g_mtx = pthread_mutex_initializer;

pthread_cond_t g_full = pthread_cond_initializer; // 滿倉

pthread_cond_t g_empty = pthread_cond_initializer; // 空倉

// 顯示庫存

void show (const char* who, const char* op, char prod)

// 生產者執行緒

void* producer (void* arg)

char prod = 'a' + rand () % 26;

show (who, "

g_storage[g_stock++] = prod;

pthread_cond_broadcast (&g_empty);

pthread_mutex_unlock (&g_mtx);

usleep ((rand () % 100) * 1000);

} return null;

}// 消費者執行緒

void* customer (void* arg)

char prod = g_storage[--g_stock];

show (who, "->", prod);

pthread_cond_broadcast (&g_full);

pthread_mutex_unlock (&g_mtx);

usleep ((rand () % 100) * 1000);

} return null;

}int main (void)

if ((error = pthread_attr_setdetachstate (&attr,//修改執行緒分離狀態屬性

pthread_create_detached)) != 0)

pthread_t tid;

if ((error = pthread_create (&tid, &attr, producer,

"生產者1")) != 0)

if ((error = pthread_create (&tid, &attr, producer,

"生產者2")) != 0)

if ((error = pthread_create (&tid, &attr, customer,

"消費者1")) != 0)

if ((error = pthread_create (&tid, &attr, customer,

"消費者2")) != 0)

getchar ();

return 0;

}

注意:

1.處於分離狀態的執行緒終止後自動釋放執行緒資源,且不能被pthread_join函式等待

2. 進行條件再判斷的原因:兩個生產者,兩個消費者,signal一次只能叫醒乙個,所以現在使用broadst廣播出去假設現在生產者生產了乙個產品,他就廣播一下,這時候倆消費者都醒了,其中乙個拿到鎖然後消耗了資源,再解鎖,這時候另乙個直接拿到鎖,然而此時已經沒產品,溢位導致段錯誤(如下圖)。這就是條件被別人消耗了的導致的情況。

4.哲學家就餐問題:

五個哲學家圍坐在一張圓桌周圍,每個哲學家面前都有一盤通心粉。由於通心粉很滑,所以需要兩把叉子才能夾住。相

鄰兩個盤子之間放有一把叉子。哲學家的生活中有兩種交替

活動時段:即吃飯和思考。當乙個哲學家覺得餓了時,他就

試圖分兩次去取其左邊和右邊的叉子,每次拿一把,但不分

次序。如果成功地得到了兩把叉子,就開始吃飯,吃完後放

下叉子繼續思考。那麼

我們要做的就是為每乙個哲學家寫一段描述其行為的程式,

且決不會死鎖嗎?

解決方案:讓哲學家不看筷子看人,如果兩邊的人都沒吃,就自己吃,吃完後就通知兩邊的人。

#include #include #include #include #include #define diners 5 // 就餐人數

// 就餐者狀態

typedef enum tag_state estat;

pthread_mutex_t g_mtx = pthread_mutex_initializer;

// 就餐者條件變數陣列

pthread_cond_t g_conds[diners] = ;

// 就餐者姓名陣列

const char* g_names[diners] = ;

// 就餐者狀態陣列

estat g_stats[diners] = ;

// 吃飯

void eat (int i)

g_stats[i] = eating;

printf ("%s:終於可以吃一口了!\n", g_names[i]);

pthread_mutex_unlock (&g_mtx);

usleep ((rand () % 100) * 10000); //吃的時間隨機給出

}// 思考

void think (int i)

// 就餐者執行緒

執行緒同步 條件變數

當我們需要控制對記憶體資源的訪問的時候,可以用一種簡單的加鎖的方法來控制,即互斥鎖。但互斥鎖有乙個明顯的缺點,就是它只有兩個狀態 鎖定和非鎖定。而條件變數通過允許執行緒阻塞和等待另乙個執行緒傳送訊號的方法彌補來互斥鎖的不足。條件變數通常和互斥鎖一起使用。使用過程 1.呼叫pthread mutex ...

執行緒同步 條件變數

多執行緒中條件變數的使用 執行緒同步之條件變數 include include include include include include include include using namespace std 乙個簡單的緩衝區類 struct buffer bool full return f...

執行緒同步 條件變數

條件變數本身不是鎖!但它也可以造成執行緒阻塞。通常與互斥鎖配合使用。給多執行緒提供乙個會合的場所。pthread cond init函式 pthread cond destroy函式 pthread cond wait函式 pthread cond timedwait函式 pthread cond ...