【并发编程】-- 读写锁、死锁

21 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

注意点:

​ Condition就是读写锁的核心。写优先,读写平衡的策略,如果是写优先。

Condition应该如下:

Condition{
	//如果当前有写任务等待或者当前是写任务,则阻塞
	if(hasWriterWait || currentIsWriter){
		return false;
	}
	//如果当前是读任务,则唤醒所有等待的任务
	if(thisIsReader){
		signalReader();
	}
	return true;
}

如果是读写平衡的公平策略,Condition应该如下:

Condition{
    //如果下一个任务是写任务等待或者当前是写任务,则阻塞
    if(nextWriterWait || currentIsWriter){
        return false;
    }
    //如果当前是读任务,则唤醒所有等待的读任务
    if(thisIsReader){
        signalReader();
    }
    return true;
}

上述代码将hasWriterWait换成了nextWriterWait,作用是看看下一个等待的任务是什么,如果是写任务,则唤醒它(而不是看有没有写任务),如果是读任务,则唤醒一系列等待的读任务,知道碰到下一个写任务为止。简单而言,所有任务都在队列中排队,如果队列为r1-r2-r3-w1-r4-r5-w2,这里是r1任务先来,由于是读任务,因此r2、r3可以同时获得锁,也称为读锁,在w1排队中,因为读写不能兼容,当任务r1、r2、r3执行完成时,才会唤醒w1写任务,当写任务执行时,r4、r5、w2任务不能执行。注意,当w1释放写锁后,根据不同的策略会有不同的选择,如果是写优先,那么将w2移到w1的后面,唤醒w1;如果是公平策略,则唤醒r4和r5读任务。

​ 可以看出读写锁适用的是读多写少的场景,几乎不会涉及到锁操作,如果是写多读少,使用读写锁并不会起到太大作用,就会退化成普通的互斥锁。

死锁

死锁是由于资源争用而导致的一种特殊现象,即任务彼此之间互相等待,导致谁也不能得到执行的一种现象。

死锁情况有以下:

  • 有两个资源。
  • 任务a获取到一个资源。
  • 任务b获取到一个资源。
  • 任务a需要任务b所获得的资源才能执行。
  • 任务b需要任务a所获得的资源才能执行。
  • 任务a不释放自己获得的资源。
  • 任务b不释放自己获得的资源。
  • 死锁。