c 遞歸互斥量(recursive mutex)

說遞歸互斥量前,說下互斥量都有哪些,apue第三版上說有下面4種:c++

  • PTHREAD_MUTEX_NORMAL:標準類型,不作任何特殊的錯誤檢查或者死鎖檢測。shell

    在同一個線程裏去鎖一個尚未解鎖的互斥量時,發生死鎖。centos

  • 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裏,互斥量類型的定義以下:centos7

/* 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就沒法給互斥量加鎖,致使一直阻塞在①處。code

爲了可以讓線程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

相關文章
相關標籤/搜索