說遞歸互斥量前,說下互斥量都有哪些,apue第三版上說有下面4種:
-
PTHREAD_MUTEX_NORMAL:標准類型,不做任何特殊的錯誤檢查或者死鎖檢測。
在同一個線程里去鎖一個還沒有解鎖的互斥量時,發生死鎖。
-
PTHREAD_MUTEX_RECURSIVE:遞歸類型。
此互斥量類型允許同一線程在互斥量解鎖前對該互斥量進行多次加鎖。遞歸互斥量維護鎖的計數,在解鎖次數和加鎖次數不相同的情況下,不會釋放鎖,別的線程就無法加鎖此互斥量。
-
PTHREAD_MUTEX_ERRORCHECK:提供錯誤檢測。如果在同一個線程里去鎖一個還沒有解鎖的互斥量,會報告錯誤。但在centos7(3.10.0-957.el7.x86_64),gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)上測試過,發現:在同一個線程里去鎖一個還沒有解鎖的互斥量,沒有報告錯誤。
-
PTHREAD_MUTEX_DEFAULT
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)環境里pthread.h里,互斥量類型的定義如下:
/* Mutex types. */
enum
{
PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
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
};
下面的例子驗證遞歸互斥量.
例子很簡單,在main函數里創建2個線程,在線程1的函數fn1,加鎖互斥量2次,但是只解鎖一次。線程fn2就無法給互斥量加鎖,導致一直阻塞在①處。
為了能夠讓線程fn1能夠先給互斥量加鎖,在fn2里調用了sleep函數,讓fn2先睡眠1秒,所以fn1就能夠先給互斥量加鎖了。
去掉②處的注釋,fn2就能鎖定mutex了,程序就不會出現死鎖狀態了。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
pthread_mutex_t mt;
int i = 0;
void* fn1(void* agr)
{
int err;
pthread_mutex_lock(&mt);
if((err = pthread_mutex_lock(&mt)) < 0)
{
printf("%s\n", strerror(err));
exit(1);
}
++i;
printf("%d\n", i);
//pthread_mutex_unlock(&mt);//-------②
pthread_mutex_unlock(&mt);
}
void* fn2(void* arg)
{
sleep(1);//目的是讓線程fn1先執行。
pthread_mutex_lock(&mt);//-----------①
++i;
printf("second %d\n", i);
pthread_mutex_unlock(&mt);
}
int main()
{
pthread_t tid1, tid2;
pthread_mutexattr_t mat;
pthread_mutexattr_init(&mat);
//設置鎖的類型為遞歸鎖
pthread_mutexattr_settype(&mat, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mt, &mat);
pthread_create(&tid1, NULL, fn1, NULL);
pthread_create(&tid2, NULL, fn2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&mt);
}
c/c++ 學習互助QQ群:877684253 本人微信:xiaoshitou5854