chenBright opened a new issue, #2209: URL: https://github.com/apache/brpc/issues/2209
**Is your feature request related to a problem? (你需要的功能是否与某个问题有关?)** > 我们需要写以某种形式和读同步,但读之间相互没竞争。一种解法是,读拿一把thread-local锁,写需要拿到所有的thread-local锁。具体过程如下: > > - 数据分前台和后台。 > - 读拿到自己所在线程的thread-local锁,执行查询逻辑后释放锁。 > - 同时只有一个写:修改后台数据,切换前后台,挨个获得所有thread-local锁并立刻释放,结束后再改一遍新后台(老前台)。 以上是brpc[DoublyBufferedData](https://github.com/apache/brpc/blob/master/docs/cn/lalb.md#doublybuffereddata)读写同步的原理。 目前在使用DoublyBufferedData时有个比较容易出问题的地方:因为查询逻辑在thread-local锁的临界区内,如果查询逻辑包含了一些会挂起bthread的操作(如协程锁、bthread_usleep、rpc等),这种在线程锁临界区内加协程锁的逻辑会导致死锁问题。 另一方面,在使用DoublyBufferedData过程中,确实有在查询逻辑中加协程锁的需求。 **Describe the solution you'd like (描述你期望的解决方法)** 减小thread-local锁的临界区,让查询逻辑不在thread-local锁的临界区,实现一种支持在查询逻辑中挂起bthread的新DoublyBufferedData数据结构。 对于目前的DoublyBufferedData,当一个读正在发生时,它会拿着所在线程的thread-local锁,这把锁会挡住同时进行的写,从而保证前台数据不会被修改。为了减小thread-local锁的临界区,在原来DoublyBufferedData的基础上,每把thread-local引入引用计数ref0、ref1和条件变量cond0、cond1,其中引用计数分别表示否有正在读buffer0或者buffer1的读者数量,而条件变量则用来进行读写同步,通知写者对应的buffer已经没有在读的了。具体过程: - 读拿到自己所在线程的thread-local锁,对当前读的buffer对应的引用计数加一,释放锁。 - 执行查询逻辑。 - 读拿到自己所在线程的thread-local锁,对当前读的buffer对应的引用计数减一,如果引用计数为0,且有写在等,则通过当前读buffer对应的条件变量通知写,最后释放锁。 - 同时只有一个写:修改后台数据,切换前后台,挨个获得所有thread-local锁。每获取一把thread-local锁,判断新后台的引用计数是否为0,如果不为0,则等在新后台对应的条件变量上;如果为0,则释放thread-local锁。所有thread-local锁获取并释放后,再改一遍新后台(老前台)。 **Describe alternatives you've considered (描述你想到的折衷方案)** **Additional context/screenshots (更多上下文/截图)** -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
