Linux 多執行緒同步與互斥

2021-10-10 20:46:10 字數 4797 閱讀 6673

在linux的多執行緒同步與互斥中,主要提供了訊號量的同步方式,以及互斥鎖和條件變數等訪問共享資源的方式。

訊號量主要用於執行緒間的同步操作,兩個執行緒協同完成一件事情,在乙個執行緒完成乙個動作後,該需要通知另外乙個執行緒,進行相應的操作。

1.1 需要包含的標頭檔案

#include
1.2 定義乙個全域性的訊號量
static sem_t g_***_sem;

/* sem :傳入的訊號量變數

pshared :是否多個執行緒共享,傳0即可

value :訊號量的初始值,如果是二值訊號量則傳入1,普通訊號量直接傳0

*/ int sem_init(sem_t *sem,int pshared,unsigned int value);

1.3 等待和釋放訊號量
//等待和釋放 

int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

int sem_post(sem_t *sem);

sem_wait()函式每呼叫一次,其值就會減1,當值等於0時,將掛起等待.

sem_trywait()函式每呼叫一次,其值就會減1,當值等於0時,將返回-1,不等待

sem_timedwait()最多等待的絕對時間,超時返回-1.

sem_post()函式每呼叫一次,其值就會加1.

超時等待毫秒的訊號量獲取函式如下:

摘自網友:

int sem_timedwait_millsecs(sem_t *sem, long msecs)

1.4 獲取訊號量當前的值
int sem_getvalue(sem_t *sem, int *sval);
eg:

static sem_t g_sem;

static int value = 0;

sem_getvalue(&g_sem,&value);

printf("sem value = %d\r\n",value);

訊號量主要用於執行緒之間的同步,而互斥鎖則主要用於對共享資源的互斥訪問。在linux中,posix定義乙個鎖型別的結構。互斥鎖可以保證每次只有乙個執行緒來訪問共享資源。

2.1 需要包含的標頭檔案

#include
2.2 互斥鎖的定義和建立
//靜態定義乙個互斥鎖

pthread_mutex_t mutex = pthread_mutex_initializer;

//動態建立乙個互斥鎖

/* restrict_mutex : 傳入的互斥鎖

restrict_attr : 互斥鎖的屬性,使用預設屬性,直接傳null即可

返回值:0---成功

*/int pthread_mutex_init(pthread_mutex_t *restrict_mutex,const pthread_mutexattr_t *restrict_attr)

2.3 互斥鎖的加解鎖
//加鎖

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

//解鎖

int pthread_mutex_unlock(pthread_mutex_t *mutex);

pthread_mutex_lock()和pthread_mutex_trylock()功能類似,區別在於如果當前的鎖被占用時,pthread_mutex_lock()會掛起等待,而pthread_mutex_trylock()則是返回ebusy。

2.4 互斥鎖的銷毀

pthread_mutex_destroy(pthread_mutex_t *mutex);
使用pthread_mutex_init()函式初始化的互斥鎖,在不需要時,需要將其銷毀。

2.5 總結

1.對於多執行緒訪問共享資源時,請務必使用鎖

2.訪問前加鎖,訪問完畢後,務必要解鎖

3.加解鎖的時間要盡量的短(即訪問共享資源的時間要短)

4.如果涉及到巢狀鎖,需要按照一定的順序加鎖,然後按照相反的順序解鎖。

通常情況下,在多執行緒程式設計中僅僅使用互斥鎖來完成互斥是可以滿足需求的,但是在一些特殊的場合,卻是不夠用的。

如:假設有兩個執行緒,t1和t2,在這兩個執行緒裡面需要迴圈對乙個共享變數sum進行自增操作,這種情況下,僅僅用互斥鎖就可以保證操作正確完成,偽**如下所示

void *thread_1_2_handler(void *parameter)

}

但是如果這事需要增加另外乙個執行緒t3,在該執行緒裡面需要判斷sum的值是否大於100時,將sum的值清0。那麼t3的偽**可以這樣實現:

void *thread_3_handler(void *parameter)

else}}

以上**存在以下問題:

1.sum的值在大多數的情況下不會到達100,對於t3的**來說,大多數都是走的else流程,即加鎖–啥都不敢–解鎖–休眠,浪費了cpu的處理時間。

2.為了節省cpu的時間,t3在sum的值沒有到達100的時候,會休眠一段時間,這樣意味著t3的響應速度將會下降,如果程式足夠快的情況下,可能在sum到達200的時候,t3才會執行清0操作。

時間和效率出現了矛盾,而條件變數恰恰是解決這個問題的最好方法。【示例**在文末】

3.1 條件變數初始化

//靜態

pthread_cond_t cond = pthread_cond_initializer;

//動態

int pthread_cond_init(pthread_cond_t *restrict_cond,const pthread_condattr_t *restrict_attr);

3.2 條件變數等待和通知
//等待

int pthread_cond_wait(pthread_cond_t *restrict_cond,pthread_mutex_t *restrict_mutex);

int pthread_cond_timedwait(pthread_cond_t *restrict_cond,pthread_mutex_t *restrict_mutex,

const struct timespec *restrict_abstime);

//通知

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

條件變數是與條件測試一起使用的,通常執行緒會對乙個條件進行測試,如果條件不滿足就會呼叫條件等待函式來等待條件滿足。

當另外乙個執行緒修改了某引數可能使得條件變數所關聯的條件變為真時,它應該通知乙個或者多個等待在條件變數等待佇列中的執行緒。

如例子中的sum>100即為條件。

所以在t1和t2執行緒中如果判斷該條件為真,則呼叫pthread_cond_signal()函式來通知t3執行緒

t3執行緒一直在等待這個訊息。

3.3 條件變數銷毀

int pthread_cond_destroy(pthread_cond_t *cond);
示例**如下:

#include #include #include #include static int sum = 0;

static pthread_mutex_t g_sum_mutex = pthread_mutex_initializer;

static pthread_cond_t g_sum_ready_cond = pthread_cond_initializer;

static void *thread_1_2_handler(void *parameter)

usleep(1);//主動讓出cpu,不然會出現乙個執行緒執行結束,另乙個執行緒才會執行

}return null;

}static void *thread_3_handler(void *parameter)

sum = 0;

printf("thread_%d:clear sum value!\r\n",(long) parameter);

pthread_mutex_unlock(&g_sum_mutex);

return null;

}int main(int argc,char *ar**)

pthread_create(&thread_id[2],null,thread_3_handler,(void *)3);

for(i = 0; i < 3; i ++)

return 0;

}

執行 gcc cond_test.c -o cond_test -lpthread

多執行緒同步與互斥

1.互斥 include include include include include pthread mutex t mutex pthread mutex initializer int lock var 0 time t end time void pthread1 void arg voi...

Linux 多執行緒同步(互斥量)

threadrace.c include include include include int myglobal pthread mutex t work mutex pthread mutex initializer 定義互斥量 初始化互斥量 pthread mutex init work mu...

Linux多執行緒同步 互斥鎖

當多個執行緒對同乙個資源進行訪問的時候,為了這個資源的安全性,我們需要對這個資源進行鎖定,規定同一時間只有乙個資源能夠獲得該鎖的鑰匙,其它執行緒要獲得該資源需要等待該執行緒 互斥鎖建立 pthread mutex t mutex 互斥鎖初始化 mutex pthread mutex initiali...