C語言學習之執行緒同步 mutex鎖 條件變數

2021-09-29 17:09:28 字數 4662 閱讀 2742

#include

//靜態初始化乙個mutex型別的變數

pthread_mutex_t fastmutex = pthread_mutex_initializer;

int pthread_mutex_init(pthread_mutex_t *mutex,

const pthread_mutexattr_t *mutexattr);

功能: 使用預設的屬性初始化mutex鎖.

引數:mutex 指定要初始化的mutex鎖

mutexattr null 使用預設的屬性初始化mutex鎖

返回值:

總是返回0

int pthread_mutex_lock(pthread_mutex_t *mutex);

功能: 如果mutex鎖目前是unlocked狀態,當前執行緒鎖定這把鎖,立即返回,如果mutex鎖已經被其他執行緒鎖定,當前執行緒掛起直到鎖被解除

引數:mutex 指定要操作的mutex鎖

返回值:

成功 0

錯誤 非0的錯誤碼

int pthread_mutex_trylock(pthread_mutex_t *mutex);

功能:如果unlocked,立即上鎖,否則,返回error code ebusy

引數:mutex

返回值:

成功 0

錯誤 非0的錯誤碼

int pthread_mutex_unlock(pthread_mutex_t *mutex);

功能:解鎖 解除的鎖一定是被當前執行緒占有的 並且被鎖定的

引數:mutex 指定要解除的鎖

返回值:

成功 0

錯誤 非0的錯誤碼

int pthread_mutex_destroy(pthread_mutex_t *mutex);

功能: 銷毀mutex鎖 釋放資源

引數:mutex 指定要被銷毀的mutex鎖

返回值:

成功 0

錯誤 非0的錯誤碼

mutex.c

#include

#include

int v =0;

//靜態初始化mutex鎖,也可以呼叫pthread_mutex_init()

pthread_mutex_t mut = pthread_mutex_initializer;

void

*handle

(void

*arg)

return

null;}

intmain

(void

)

執行結果:

執行分析:如果不加mutex鎖的情況下,開兩個執行緒執行handle方法,由於兩個執行緒共享全域性變數v,所以tmp不會打到2000,加了鎖之後,同一時刻只有乙個執行緒可以訪問全域性變數v,所以tmp最終會到2000.

鎖只能保證同一時刻只有乙個執行緒訪問公共資源,但並不能很好的協調兩個執行緒工作。比如,如果實現生產者消費者模型,將v作為公共資源,生產者執行緒使v增加,消費者執行緒使v減少,當v為0時消費者不能消費。在實現這個模型時,如果只是用mutex鎖實現,相當於兩個執行緒無論在什麼情況下,都會是公平的競爭公共資源,但有時我們並不希望這樣。比如,當v為0時,我們不希望消費者執行緒再占用cpu資源,直接讓生產者控制全域性變數v就好,但是mutex會公平地讓兩個執行緒競爭。如果消費者執行緒競爭勝利,那麼由於v=0,消費者只是if(v=0) do nothing 的語句執行一下,白白占用cpu,而實際情況我們更希望在這種情況下,直接讓消費者讓出cpu,直接讓生產者控制,直至v>0時,兩個執行緒再公平競爭。這時,就需要用到條件變數。

pthread_cond_t 條件變數型別

//靜態初始化乙個條件變數pthread_cond_t cond = pthread_cond_initializer;

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

功能: 使用預設屬性初始化條件變數

引數:cond 指定要初始化的條件變數

cond_attr null 使用預設的屬性

返回值:成功返回0,失敗返回errno

int pthread_cond_signal(pthread_cond_t *cond);

功能:從等著條件變為真的執行緒中取出乙個重新執行.如果沒有執行緒等待條件變為真那麼什麼都不發生.

引數:cond 指定條件變數 等著這個條件變為真

返回值:成功返回0,失敗返回errno

int pthread_cond_broadcast(pthread_cond_t *cond);

功能:重新啟動所有等待條件為真的執行緒.如果沒有執行緒等待條件為真,什麼都不做

引數:cond 指定具體的條件變數 等著這個條件變為真

返回值:成功返回0,失敗返回errno

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

功能:解鎖(使用這個函式之前,一定加鎖),掛起等待cond is signaled,直到cond is signaled該函式返回,返回之前重新獲得鎖(重新上鎖)

引數:cond 指定要操作的條件變數

mutex 使用到的mutex鎖

返回值:成功返回0,失敗返回errno

該函式通常配合while語句使用,當while條件滿足時,則呼叫該函式阻塞,當其他執行緒完成某項工作,使while條件滿足了,就呼叫signal函式,wait函式返回並重新獲得鎖,回到while迴圈,由於此時條件不滿足,則不在進入迴圈呼叫wait,執行迴圈之後的語句

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

功能:帶計時的wait

int pthread_cond_destroy(pthread_cond_t *cond);

功能:銷毀條件變數

引數:cond 指定要銷毀的條件變數

返回值:

成功 0

錯誤 非0

用條件變數實現上述生產者消費者模型(不對生產者限制,只限制消費者,只有有貨物時才可以消費)

cond.c

#include

#include

#include

#include

#include

//定義節點型別

typedef

struct nodenode_t;

node_t *head =

null

;//定義乙個空鍊錶

pthread_mutex_t mutex;

//定義乙個鎖

pthread_cond_t cond;

//定義乙個條件變數

//生產者執行緒

void

*p_func

(void

*arg)

return

null;}

//消費者執行緒

void

*c_func

(void

*arg)

//從鍊錶的頭部摘取乙個節點

tmp = head;

head = head->next;

//解鎖

pthread_mutex_unlock

(&mutex)

;//消費摘取的節點

printf

("c:%d\n"

, tmp->data)

;free

(tmp)

; tmp =

null

;//休眠1~4秒

sleep

(rand()

%4+1

);}return0;

}int

main

(void

)

用訊號和自定義訊號處理函式及pause函式模擬用條件變數實現的生產者消費者模型:只是模擬,方便深入理解條件變數的過程,很多細節肯定是條件變數更優。int v作為公共變數,生產者使它增加,消費者使它減少.

#include

#include

#include

#include

#include

#include

#include

void

my_block

(int n)

int v =0;

//靜態初始化mutex鎖,也可以呼叫pthread_mutex_init()

pthread_mutex_t mut = pthread_mutex_initializer;

void

*producer

(void

*arg)

}void

*consumer

(void

*arg)

else

pthread_mutex_unlock

(&mut)

;sleep

(rand()

%3+1

);}}

intmain

(void

)

執行緒同步之mutex篇

原理 當乙個互斥物件不再被乙個執行緒所擁有,它就處於發訊號狀態。此時首先呼叫waitforsingleobject 函式的執行緒就成為該互斥物件的擁有者,此互斥物件設為不發訊號狀態。當執行緒呼叫releasemutex 函式並傳遞乙個互斥物件的控制代碼作為引數時,這種擁有關係就被解除,互斥物件重新進...

執行緒同步之互斥量Mutex

前面的文章介紹了執行緒的建立 終止 連線和分離。本篇介紹執行緒的同步。多執行緒的難點是對共享資源的訪問,如何保證多個執行緒能夠 同時 訪問同乙個共享資源而又不引起衝突,就是執行緒同步的本質。互斥量用來確保共享資源同時只被乙個執行緒訪問。互斥量有兩種狀態 已鎖定 locked 和未鎖定 unlocke...

C 多執行緒同步 二 Mutex

monitor和lock多用於鎖定被呼叫端,而mutex則多用鎖定呼叫端。lock this 或者是用monitor也是一樣的,如下 monitor.enter this do something monitor.exit this monitor的好處是可以用tryenter this,timeo...