递归锁和非递归锁

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步已经加读锁]

  

posted on 2020-06-10 22:17  能量星星  阅读(1094)  评论(0编辑  收藏  举报

导航