互斥鎖
-
互斥鎖用來保證一段時間內只有一個線程在執行一段代碼(保證共享數據的完整性)
-
互斥鎖變量
typedef union{ struct __pthread_mutex_s __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; } pthread_mutex_t;
-
互斥鎖的生成
/* Initialize a mutex. */ extern int pthread_mutex_init (pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr) __THROW __nonnull ((1));
用於動態創建一個互斥鎖,第一個參數爲互斥鎖指針,第二個參數爲互斥鎖屬性(通常傳
NULL
表示默認屬性)
互斥鎖屬性
-
屬性結構
/* Data structures for mutex handling. The structure of the attribute type is not exposed on purpose. */ typedef union{ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; int __align; } pthread_mutexattr_t;
互斥鎖屬性使用上面的聯合體存放,通過函數
pthread_mutexattr_setpshared()
設置範圍屬性, -
範圍屬性
/* Process shared or private flag. */ enum{ PTHREAD_PROCESS_PRIVATE,//同進程中線程同步 #define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_SHARED //不同進程中的線程同步 #define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED };
-
類型屬性
通過函數pthread_mutexattr_settype()
(通常使用默認屬性PTHREAD_MUTEX_DEFAULT
)/* Mutex types. */ enum{ //缺省值,普通鎖,當一個線程加鎖以後,其餘請求鎖的線程將會形成一個等待隊列 //並在解鎖後按照先後順序獲得鎖,資源分配公平 PTHREAD_MUTEX_TIMED_NP, //嵌套鎖,允許同一線程對同一鎖成功獲得多次,並通過多次unlock解鎖 //如果是不同線程請求,則在加鎖線程解鎖時重新競爭 PTHREAD_MUTEX_RECURSIVE_NP, //檢錯鎖,如果同一線程請求同一個鎖,則返回EDEALK //否則與普通鎖類型動作相同,這樣保證當不允許多次時,不會出現最簡單的死鎖 PTHREAD_MUTEX_ERRORCHECK_NP, //適應鎖,動作最簡單的類型,僅等待解鎖以後重新競爭 PTHREAD_MUTEX_ADAPTIVE_NP #if defined __USE_UNIX98 || defined __USE_XOPEN2K8 , PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL #endif #ifdef __USE_GNU /* For compatibility. */ , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP #endif };
-
Demo
static void init_thread_mutex(void) { pthread_mutexattr_t mutex_attr; //PTHREAD_PROCESS_SHARED pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_PRIVATE); pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_DEFAULT); //使用上面的屬性初始化thread_data_mutex互斥鎖 pthread_mutex_init(&thread_data_mutex, &mutex_attr); }
上鎖操作
-
加鎖
lock ()
、解鎖unlock()
、測試加鎖trylock()
不論是哪種類型的鎖,都不可能被兩個不同的線程得到,而必須等待解鎖,對於普通鎖
和適應鎖
,解鎖者可以說同進程
內的任何線程,而對於檢錯鎖
必須由加鎖者解鎖,嵌套鎖
也是由加鎖者解鎖 -
同一進程中的線程,如果枷鎖後沒有解鎖,任何其他線程都無法在獲得鎖,也就是常說的
死鎖
-
上鎖
/* Lock a mutex. */ extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROWNL __nonnull ((1));
當一個線程執行到
pthread_mutex_lock
處時,如果該鎖此時被其他線程線程調用,那麼此線程會阻塞,一直等另外一個線程釋放鎖,然後嘗試請求鎖。 -
解鎖
/* Unlock a mutex. */ extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROWNL __nonnull ((1));
靜態鎖
-
使用宏
PTHREAD_MUTEX_INITIALIZER
初始化pthread_mutex_t static_data_mutex = PTHREAD_MUTEX_INITIALIZER;
-
靜態鎖初始化以後就可以直接使用,進行加鎖解鎖,和動態鎖類型,唯一不用的是,當調用
pthread_mutex_trylock()
時,如果正忙則返回EBUSY
而不是掛起等待
鎖的銷燬
- 銷燬鎖,意味着釋放它所佔用的所有資源,且要求鎖當前處於開發狀態
* Destroy a mutex. */ extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW __nonnull ((1));
- 在Liunx中,互斥鎖不佔用任何資源,因此Linux Threads中的
pthread_mutex_destroy()
除了檢查鎖的狀態外沒有其他任何操作(忙就返回EBUSY
)
完整Demo
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//自定義數據結構,用於測試
typedef struct ThreadData_t {
pthread_t m_pid;
char* m_threadName;
} ThreadData;
ThreadData threadData;
pthread_mutex_t thread_data_mutex;
pthread_mutex_t static_data_mutex = PTHREAD_MUTEX_INITIALIZER;
static void init_thread_mutex(void) {
pthread_mutexattr_t mutex_attr;
//PTHREAD_PROCESS_SHARED
pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_PRIVATE);
pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_DEFAULT);
pthread_mutex_init(&thread_data_mutex, &mutex_attr);
}
static void destory_thread_mutex(void) {
pthread_mutex_destroy(&thread_data_mutex);
}
//線程函數routine
static void* test_thread1(void* thread_name) {
fprintf(stderr, "%s try to lock!\n", (char*)thread_name);
pthread_mutex_lock(&thread_data_mutex);
threadData.m_pid = pthread_self();
threadData.m_threadName = (char*)thread_name;
fprintf(stderr, "%s mutex locked! \n", threadData.m_threadName);
sleep(5);
pthread_mutex_unlock(&thread_data_mutex);
return NULL;
}
static void* test_thread2(void* thread_name) {
fprintf(stderr, "%s try to lock!\n", (char*)thread_name);
pthread_mutex_lock(&thread_data_mutex);
threadData.m_pid = pthread_self();
threadData.m_threadName = (char*)thread_name;
fprintf(stderr, "%s mutex locked! \n", threadData.m_threadName);
sleep(6);
pthread_mutex_unlock(&thread_data_mutex);
return NULL;
}
int main(int argc, char** argv) {
pthread_t pid1, pid2;
init_thread_mutex();
if (pthread_create(&pid1, NULL, test_thread1, (void*)"test thread1") != 0) {
fprintf(stderr, "create thread1 failed\n");
return -1;
}
if (pthread_create(&pid2, NULL, test_thread2, (void*)"test thread2") != 0) {
fprintf(stderr, "create thread2 failed\n");
return -1;
}
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
destory_thread_mutex();
return 0;
}