多线程:多读少写锁(Readers–writer lock)

先来几个同义词

  • readers–writer (RW) lock
  • shared - exclusive lock
  • multiple readers/single-writer lock
  • multi-reader lock
  • push lock

解决的问题

  1. 允许多个线程同时读取数据。只允许一个线程写或更新数据
  2. 写数据时,其他的写操作和读操作要被阻塞。(SQLite 的 WAL 不是,允许同时读写)

实现时需要考虑的问题

读优先还是写优先?
读优先的概述如下:

尽量满足并发的读操作,当已经有线程在读数据的时候,其他读线程无需等待,而写线程需要等待所有正在进行的读操作之后才能执行

写优先的概述如下:

尽量满足写操作,尽管写操作不能并发,但是可以排队,优先于等待的读线程获得执行权

对系统刷新要求的高标准系统,应该使用写优先的锁,比如路由器、证券交易平台。通常用很多读请求,如果等所有读请求都结束,可能更新信息已经来不及了,即发生 starvation 问题。

解决问题的思路

Readers–writer locks are usually constructed on top of mutexes and condition variables, or on top of semaphores.

  • 互斥量+条件变量
  • 信号量

具体实现参见参考资料。
默认实现都是读优先的锁。如果要实现写优先的锁,可以通过加标记位判断是否有写请求在等待。

读写锁重入问题及死锁

通常reader lock是可重入的,writer lock是不可重入的。但是为了防止writer饥饿,writer lock通常会阻塞后来的reader lock,因此reader lock在重入的时候可能死锁。

即获取读锁,尝试获取写锁(为了防止饥饿,不允许再次获取读锁),进行重入,即尝试获取读锁。
bingo,发生死锁啦

参考

posted on 2018-01-07 22:59  花老🐯  阅读(1237)  评论(0编辑  收藏  举报

导航