递归锁和非递归锁
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步已经加读锁]