1. 程式人生 > >執行緒同步的幾種方式

執行緒同步的幾種方式

多個執行緒同時訪問共享資料可能會衝突。比如兩個執行緒同時把某個全域性變數增加1需要3步。

1.從記憶體讀取變數到暫存器
2.把暫存器中變數值加一
3.把結果返回給記憶體
不同執行緒的執行時間會造成結果的不同,這時候就需要執行緒同步:

執行緒同步的四種方式:

  • 互斥量(mutex):引入互斥鎖,得到鎖的執行緒執行(讀,修改,寫)的操作,沒有獲得鎖的執行緒只能等待,不能共享資料。(讀,寫,修改)的操作就有了原子性(要麼執行,要麼不執行),不會被打斷,避免了執行緒混亂。
    #include <pthread.h>
    int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);//鎖的初始化
    int pthread_mutex_destroy(pthread_mutex_t *mutex); //銷燬

  • 條件變數
    利用執行緒間共享的全域性變數進行同步的一種機制。條件變數上的基本操作有:觸發條件(當條件變為 true 時);等待條件,掛起執行緒直到其他執行緒觸發條件。

一個條件變數總是和一個和互斥鎖一起使用。

int pthread_cond_init(pthread_cond_t*cond,pthread_condattr_t *cond_attr); //初始化   
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);//執行緒呼叫可以在條件變數上阻塞等待(釋放mutex, 阻塞等待,獲得mutex) 
int
pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);//可以設定等待時間,如果到時還沒有被喚醒,就返回 int pthread_cond_destroy(pthread_cond_t *cond); //銷燬 int pthread_cond_signal(pthread_cond_t *cond); //喚醒某個在條件變數上等待的另一個執行緒 int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有執行緒的阻塞
  • 訊號量

    訊號量的型別是sem_t
#include <semaphore.h>
int sem_init (sem_t *sem , int pshared, unsigned int value);  //初始化,value表示可用的資源數,pashared為0時訊號量用於同一程序執行緒間的同步

int sem_wait(sem_t *sem);  //如果資源數大於0,則執行緒獲得資源,資源數減1,如果等於0,執行緒等待等待不為0為止

int sem_post(sem_t *sem);  //釋放資源,資源數+1,同時喚醒等待的執行緒
int sem_destroy(sem_t *sem);

  • 讀寫鎖
    讀寫鎖是一種特殊的自旋鎖。讀者寫者模型,在編寫多執行緒時有種情況很常見就是共享資源很少修改,但很多人同時訪問,比較寫,讀的機會更多一些。讀的過程伴隨著查詢,比較費時間,給這種程式碼枷鎖,效率很低,就有了讀者寫者模型。
    可以同時有多個讀者只有一個寫者。不能同時讀和寫。
#include 
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
//在初始化某個讀寫鎖的時候,如果屬性指標attr是個空指標的話,表示預設的屬性;如果想要使用非預設屬性

int pthread_rwlockattr_destroy(pthread_rwlockatttr_t *attr);

int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr);
//用來獲取讀出鎖,如果相應的讀出鎖已經被某個寫入者佔有,那麼就阻塞呼叫執行緒
int pthread_rwlock_wrlock(pthread_rwlock_t *rwptr);
//來獲取一個寫入鎖,如果相應的寫入鎖已經被其它寫入者或者一個或多個讀出者佔有,那麼就阻塞該呼叫執行緒

int pthread_rwlock_unlock(pthread_rwlock_t *rwptr);
用來釋放一個讀出或者寫入鎖