linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數和訊號量。
一、互斥鎖(mutex)
鎖機制是同一時刻只允許乙個執行緒執行乙個關鍵部分的**。
1. 初始化鎖
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
其中引數 mutexattr 用於指定鎖的屬性(見下),如果為null則使用預設屬性。
互斥鎖的屬性在建立鎖的時候指定,在linuxthreads實現中僅有乙個鎖型別屬性,不同的鎖型別在試圖對乙個已經被鎖定的互斥鎖加鎖時表現不同。當前有四個值可供選擇:
(1)pthread_mutex_timed_np,這是預設值,也就是普通鎖。當乙個執行緒加鎖以後,其餘請求鎖的執行緒將形成乙個等待佇列,並在解鎖後按優先順序獲得鎖。這種鎖策略保證了資源分配的公平性。
(2)pthread_mutex_recursive_np,巢狀鎖,允許同乙個執行緒對同乙個鎖成功獲得多次,並通過多次unlock解鎖。如果是不同執行緒請求,則在加鎖執行緒解鎖時重新競爭。
(3)pthread_mutex_errorcheck_np,檢錯鎖,如果同乙個執行緒請求同乙個鎖,則返回edeadlk,否則與pthread_mutex_timed_np型別動作相同。這樣就保證當不允許多次加鎖時不會出現最簡單情況下的死鎖。
(4)pthread_mutex_adaptive_np,適應鎖,動作最簡單的鎖型別,僅等待解鎖後重新競爭。
2. 阻塞加鎖
int pthread_mutex_lock(pthread_mutex *mutex);
3. 非阻塞加鎖
int pthread_mutex_trylock( pthread_mutex_t *mutex);
該函式語義與 pthread_mutex_lock() 類似,不同的是在鎖已經被佔據時返回 ebusy 而不是掛起等待。
4. 解鎖(要求鎖是lock狀態,並且由加鎖執行緒解鎖)
int pthread_mutex_unlock(pthread_mutex *mutex);
5. 銷毀鎖(此時鎖必需unlock狀態,否則返回ebusy)
int pthread_mutex_destroy(pthread_mutex *mutex);
示例**:
[oracle@localhost]$ cat mutextest.c
#include
#include
#include
#include
pthread_mutex_t mutex = pthread_mutex_initializer;
int gn;
void* thread(void *arg)
int main()
else
pthread_join(id, null);
pthread_mutex_destroy(&mutex);
return 0;
}示例**1:
[oracle@localhost]$ cat condtest1.c
[oracle@localhost]$
示例**2:
[oracle@localhost]$ cat condtest2.c
#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);
pthread_join(tid, null);
printf("all done -- exiting\n");
return 0;
}[oracle@localhost]$
可以看出,等待條件變數訊號的用法約定一般是這樣的:
...pthread_mutex_lock(&mutex);
...pthread_cond_wait (&cond, &mutex);
...pthread_mutex_unlock (&mutex);
...相信很多人都會有這個疑問:為什麼pthread_cond_wait需要的互斥鎖不在函式內部定義,而要使使用者定義的呢?現在沒有時間研究 pthread_cond_wait 的源**,帶著這個問題對條件變數的用法做如下猜測,希望明白真相看過源**的朋友不吝指正。
1. pthread_cond_wait 和 pthread_cond_timewait 函式為什麼需要互斥鎖?因為:條件變數是執行緒同步的一種方法,這兩個函式又是等待訊號的函式,函式內部一定有須要同步保護的資料。
2. 使用使用者定義的互斥鎖而不在函式內部定義的原因是:無法確定會有多少使用者使用條件變數,所以每個互斥鎖都須要動態定義,而且管理大量互斥鎖的開銷太大,使用使用者定義的即靈活又方便,符合unix哲學的程式設計風格(隨便推薦閱讀《unix程式設計哲學》這本好書!)。
3. 好了,說完了1和2,我們來自由猜測一下 pthread_cond_wait 函式的內部結構吧:
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
...}
三、 訊號量
如同程序一樣,執行緒也可以通過訊號量來實現通訊,雖然是輕量級的。
執行緒使用的基本訊號量函式有四個:
#include
1. 初始化訊號量
int sem_init (sem_t *sem , int pshared, unsigned int value);
引數:sem - 指定要初始化的訊號量;
pshared - 訊號量 sem 的共享選項,linux只支援0,表示它是當前程序的區域性訊號量;
value - 訊號量 sem 的初始值。
2. 訊號量值加1
給引數sem指定的訊號量值加1。
int sem_post(sem_t *sem);
3. 訊號量值減1
給引數sem指定的訊號量值減1。
int sem_wait(sem_t *sem);
如果sem所指的訊號量的數值為0,函式將會等待直到有其它執行緒使它不再是0為止。
4. 銷毀訊號量
銷毀指定的訊號量。
int sem_destroy(sem_t *sem);
示例**:
[oracle@localhost]$ cat semtest.c
#include
#include
#include
#include
#include
#include
#define return_if_fail(p) if((p) == 0)
typedef struct _privinfo
privinfo;
static void info_init (privinfo* prifo);
static void info_destroy (privinfo* prifo);
static void* pthread_func_1 (privinfo* prifo);
static void* pthread_func_2 (privinfo* prifo);
int main (int argc, char** argv)
info_init (prifo);
ret = pthread_create (&pt_1, null, (void*)pthread_func_1, prifo);
if (ret != 0)
ret = pthread_create (&pt_2, null, (void*)pthread_func_2, prifo);
if (ret != 0)
pthread_join (pt_1, null);
pthread_join (pt_2, null);
info_destroy (prifo);
return 0;
}static void info_init (privinfo* prifo)
static void info_destroy (privinfo* prifo)
static void* pthread_func_1 (privinfo* prifo)
return;
}static void* pthread_func_2 (privinfo* prifo)
return;
}[oracle@localhost]$
也可參考:
posix執行緒程式設計指南(3)
linux執行緒同步之條件變數
linux下執行緒同步之互斥鎖
互斥鎖是多執行緒同步的一種方式,當多個執行緒訪問同乙個變數時,最簡單的方法就是使用乙個互斥鎖 mutex 保護這個共享變數,防止出現資源搶占的問題。下面是未加互斥鎖時 include includepthread mutex t mutex pthread mutex initializer 靜態初...
linux下執行緒同步之條件變數
以下是生產者消費者 實現 a執行緒生產產品到共享陣列,b執行緒從中消費。include include include pthread mutex t mutex pthread mutex initializer 並且初始化鎖 pthread cond t cond pthread cond in...
Linux下執行緒
此文講述的執行緒為linux下,其執行緒庫函式是由posix標準定義的,稱為posix thread或者pthread。在linux上線程函式位於libpthread共享庫中,因此在編譯時要加上 lpthread選項。建立執行緒 終止執行緒 等待執行緒 三個函式都為pthread.h中定義,其中要注...