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步已經加讀鎖]