一、先上结论:
递归锁:同一个线程在不解锁的情况下,可以多次获取锁定同一个递归锁,而且不会产生死锁;
非递归锁:在不解锁的情况下,当同一个线程多次获取同一个递归锁时,会产生死锁。
二、典型应用:
windows下的互斥量和临界区(关键段)是递归锁;
linux下的互斥量pthread_mutex_t是非递归锁,但是可以通过在创建互斥量时设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t设置为递归锁。
三、举例
critical_section递归锁
#include <Windows.h>
#include <iostream>
#include <string>
int counter = 0;
CRITICAL_SECTION g_cs;
void doit(void* arg)
{
int i, val;
for (i=0; i<5000; i++)
{
EnterCriticalSection(&g_cs);
EnterCriticalSection(&g_cs);
val = counter;
printf("thread %d : %d\n", int(arg), val+1);
counter = val + 1;
LeaveCriticalSection(&g_cs);
LeaveCriticalSection(&g_cs);
}
}
int main(int argc, char*argv[])
{
InitializeCriticalSection(&g_cs);
HANDLE hThread1 = CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)doit, (void*)1, 0, NULL);
HANDLE hTrehad2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)doit, (void*)2, 0, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hTrehad2, INFINITE);
DeleteCriticalSection(&g_cs);
return 0;
}
结果:加1次锁和2次锁,均可以正确的输出1~10000。
pthread_mutex_t非递归锁
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int counter = 0;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
void* doit(void*)
{
int i, val;
for (i=0; i<5000; i++)
{
pthread_mutex_lock(&g_mutex);
pthread_mutex_lock(&g_mutex);
val = counter;
printf("%x: %d\n", pthread_self(), val+1);
counter = val + 1;
pthread_mutex_unlock(&g_mutex);
pthread_mutex_unlock(&g_mutex);
}
}
int main(int argc, char*argv[])
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, doit, NULL);
pthread_create(&tid2, NULL, doit, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
结果:加1次锁,可以正确的输出1~10000;加2次锁,死锁,不输出任何信息。
pthread_mutex_t递归锁
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int counter = 0;
pthread_mutex_t g_mutex;// = PTHREAD_MUTEX_INITIALIZER;
void* doit(void*)
{
int i, val;
for (i=0; i<5000; i++)
{
pthread_mutex_lock(&g_mutex);
pthread_mutex_lock(&g_mutex);
val = counter;
printf("%x: %d\n", pthread_self(), val+1);
counter = val + 1;
pthread_mutex_unlock(&g_mutex);
pthread_mutex_unlock(&g_mutex);
}
}
int main(int argc, char*argv[])
{
//create recursive attribute
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
//set recursive attribute
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&g_mutex, &attr);
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, doit, NULL);
pthread_create(&tid2, NULL, doit, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&g_mutex);
//destroy recursive attribute
pthread_mutexattr_destroy(&attr);
return 0;
}
结果:加1次锁和2次锁,均可以正确的输出1~10000。