Linux多執行緒同步的幾種方式

2021-06-10 07:02:35 字數 4410 閱讀 8863

執行緒的最大特點是資源的共享性,但資源共享中的同步問題是多執行緒程式設計的難點。linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數和訊號量。

1)互斥鎖(mutex)

通過鎖機制實現執行緒間的同步。同一時刻只允許乙個執行緒執行乙個關鍵部分的**。

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex *mutex);

int pthread_mutex_destroy(pthread_mutex *mutex);

int pthread_mutex_unlock(pthread_mutex *

(1)先初始化鎖init()或靜態賦值pthread_mutex_t mutex=pthread_mutex_initialier

attr_t有:

pthread_mutex_timed_np:其餘執行緒等待佇列

pthread_mutex_recursive_np:巢狀鎖,允許執行緒多次加鎖,不同執行緒,解鎖後重新競爭

pthread_mutex_errorcheck_np:檢錯,與一同,執行緒請求已用鎖,返回edeadlk;

pthread_mutex_adaptive_np:適應鎖,解鎖後重新競爭

(2)加鎖,lock,trylock,lock阻塞等待鎖,trylock立即返回ebusy

(3)解鎖,unlock需滿足是加鎖狀態,且由加鎖執行緒解鎖

(4)清除鎖,destroy(此時鎖必需unlock,否則返回ebusy,//linux下互斥鎖不占用記憶體資源

示例**

#include

#include

#include

#include

#include "iostream"

using namespace std;

pthread_mutex_t mutex = pthread_mutex_initializer;

int tmp;

void* thread(void *arg)

int main()

else

pthread_join(id, null);

pthread_mutex_destroy(&mutex);

return 0;

}編譯: g++ -o thread testthread.cpp -lpthread

說明:pthread庫不是linux系統預設的庫,連線時需要使用靜態庫libpthread.a,所以在使用pthread_create()建立執行緒,以及呼叫pthread_atfork()函式建立fork處理程式時,需要鏈結該庫。在編譯中要加 -lpthread引數。

2)條件變數(cond)

利用執行緒間共享的全域性變數進行同步的一種機制。條件變數上的基本操作有:觸發條件(當條件變為 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);

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); //解除所有執行緒的阻塞

(1)初始化.init()或者pthread_cond_t cond=pthread_cond_initialier(前者為動態初始化,後者為靜態初始化);屬性置為null

(2)等待條件成立.pthread_wait,pthread_timewait.wait()釋放鎖,並阻塞等待條件變數為真,timewait()設定等待時間,仍未signal,返回etimeout(加鎖保證只有乙個執行緒wait)

(3)啟用條件變數:pthread_cond_signal,pthread_cond_broadcast(啟用所有等待執行緒)

(4)清除條件變數:destroy;無線程等待,否則返回ebusy

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

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

一定要在mutex的鎖定區域內使用。

如果要正確的使用pthread_mutex_lock與pthread_mutex_unlock,請參考

另外,posix1標準說,pthread_cond_signal與pthread_cond_broadcast無需考慮呼叫執行緒是否是mutex的擁有者,也就是說,可以在lock與unlock以外的區域呼叫。如果我們對呼叫行為不關心,那麼請在lock區域之外呼叫吧。

說明:(1)pthread_cond_wait 自動解鎖互斥量(如同執行了pthread_unlock_mutex),並等待條件變數觸發。這時執行緒掛起,不占用cpu時間,直到條件變數被觸發(變數為ture)。在呼叫 pthread_cond_wait之前,應用程式必須加鎖互斥量。pthread_cond_wait函式返回前,自動重新對互斥量加鎖(如同執行了pthread_lock_mutex)。

(3)pthread_cond_timedwait 和 pthread_cond_wait 一樣,自動解鎖互斥量及等待條件變數,但它還限定了等待時間。如果在abstime指定的時間內cond未觸發,互斥量mutex被重新加鎖,且pthread_cond_timedwait返回錯誤 etimedout。abstime 引數指定乙個絕對時間,時間原點與 time 和 gettimeofday 相同:abstime = 0 表示 2023年1月1日00:00:00 gmt。

(4)pthread_cond_destroy 銷毀乙個條件變數,釋放它擁有的資源。進入 pthread_cond_destroy 之前,必須沒有在該條件變數上等待的執行緒。

(5)條件變數函式不是非同步訊號安全的,不應當在訊號處理程式中進行呼叫。特別要注意,如果在訊號處理程式中呼叫 pthread_cond_signal 或 pthread_cond_boardcast 函式,可能導致呼叫執行緒死鎖。

示例程式1

#include

#include

#include "stdlib.h"

#include "unistd.h"

pthread_mutex_t mutex;

pthread_cond_t cond;

void hander(void *arg)

void *thread1(void *arg)

pthread_cleanup_pop(0);

}void *thread2(void *arg)

}int main()

while(1);

sleep(20);

pthread_exit(0);

return 0;

}示例程式2:

#include

#include

#include "stdio.h"

#include "stdlib.h"

static pthread_mutex_t mtx = pthread_mutex_initializer;

static pthread_cond_t cond = pthread_cond_initializer;

struct node

*head = null;

static void cleanup_handler(void *arg)

static void *thread_func(void *arg)

pthread_mutex_unlock(&mtx); //臨界區資料操作完畢,釋放互斥鎖

}pthread_cleanup_pop(0);

return 0;

}int main(void)

printf("thread 1 wanna end the line.so cancel thread 2./n");

//關於pthread_cancel,有一點額外的說明,它是從外部終止子執行緒,子執行緒會在最近的取消點,退出

//執行緒,而在我們的**裡,最近的取消點肯定就是pthread_cond_wait()了。

pthread_cancel(tid);

多執行緒中線程同步的幾種方式

原連線 msdn 執行緒的非同步特性意味著必須協調對資源 如檔案控制代碼 網路連線和記憶體 的訪問。否則,兩個或更多的執行緒可能在同一時間訪問相同的資源,而每個執行緒都不知道其他執行緒的操作。結果將產生不可預知的資料損壞。對於整數資料型別的簡單操作,可以用 interlocked 類的成員來實現執行...

Linux多執行緒同步方式

當多個執行緒共享相同的記憶體時,需要確保每個執行緒看到一致的資料檢視,當多個執行緒同時去修改這片記憶體時,就可能出現偏差,得到與預期不符合的值。為啥需要同步,一件事情邏輯上一定是有序的,即使在併發環境下 而作業系統對於多執行緒不會自動幫我們序列化,所以需要我們通過作業系統提供的同步方式api,結合自...

執行緒同步的幾種方式

程序中線程同步的四種常用方式 一 臨界區 ccriticalsection 當多個執行緒訪問乙個獨占性共享資源時,可以使用臨界區物件。擁有臨界區的執行緒可以訪問被保護起來的資源或 段,其他執行緒若想訪問,則被掛起,直到擁有臨界區的執行緒放棄臨界區為止。具體應用方式 1 定義臨界區物件ccritica...