執行緒的最大特點是資源的共享性,但資源共享中的同步問題是多執行緒程式設計的難點。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...