1.遞歸鎖和非遞歸鎖含義
遞歸鎖:在同一個線程可以多次獲取同一個鎖,不會產生死鎖。
非遞歸鎖:在同一個線程中,加鎖后不可以再次獲取該鎖,如果獲取可能產生死鎖。
2.常用鎖的遞歸和非遞歸屬性
linux下的pthread_mutex_t是非遞歸鎖,但是可以通過在創建互斥量時設置PTHREAD_MUTEX_RECURSIVE屬性,將pthread_mutex_t設置為遞歸鎖。
讀寫鎖是非遞歸鎖。
盡量不要使用遞歸鎖,即同一個線程中,盡量不要重復鎖定同一個鎖,讀鎖也不可以。
另外加鎖最好避免互相嵌套,否則也容易死鎖。
3.一個死鎖
下面是使用讀寫鎖導致的死鎖問題,因為讀寫鎖是非遞歸鎖。
void *process()
{
pthread_rwlock_wrlock(&g_lock); // 2.加寫鎖,此時會一直等待,導致死鎖
pthread_rwlock_unlock(&g_lock); // 釋放寫鎖
return NULL;
}
int main()
{
pthread_rwlock_t g_lock;
pthread_rwlock_rdlock(&g_lock); // 1.第1次加讀鎖
create_thread(process); // 創建線程
sleep(5); // 等待幾秒
pthread_rwlock_rdlock(&g_lock); // 3.第2次加讀鎖,此時會一致等待,導致死鎖
pthread_rwlock_unlock(&g_lock); // 釋放第1次的讀鎖
pthread_rwlock_unlock(&g_lock); // 釋放第2次的讀鎖
}
4.另一個死鎖
下面這個死鎖出現的原因是,如果一個線程已經加讀鎖,然后第二個線程加寫鎖,則會導致第三個線程加讀鎖加不上,因為此時寫鎖優先級高。
但是在linux下面的讀寫鎖不會死鎖。
三個鎖: lock_a, lock_b, lock_c
process1()
{
write_lock(lock_a);
write_lock(lock_b);
write_unlock(lock_b);
write_unlock(lock_a);
}
process2()
{
read_lock(lock_b);
read_lock(lock_c);
read_unlock(lock_c);
read_unlock(lock_b);
}
process3()
{
read_lock(lock_c);
read_lock(lock_a);
read_unlock(lock_a);
read_unlock(lock_c);
}
process4()
{
write_lock(lock_c);
write_unlock(lock_c);
}
process1: a_write[1 ] -> b_write [加鎖不上,第3步已經加讀鎖]
process2: b_read [2 ] -> c_read [加鎖不上,第4步寫鎖先開始等的,優先級高]
process3: c_read [3 ] -> a_read [加鎖不上,第1步已經加寫鎖]
process4: c_write[4 加鎖不上,第3步已經加讀鎖]
