sync.RWMutex 解决读写问题

在一个共享的数据需要被多个线程访问的时候就会出现很多读写问题(由于读写问题有很多变种,所以用许多来形容)。有两种类型的线程需要访问数据—读线程和写线程。读线程仅仅读数据,写线程修改数据。当写线程有权限访问数据的时候,其他线程(包括读线程和写线程)是不可以访问这个共享的数据。这个限制在日常生活中是真的发生的,当写线程无法以原子性的操作修改数据的时候,读线程必须被阻塞,以防读取到脏数据(译者注:为了使得说明的更加清晰,后面用写goroutine和读goroutine分别代替写读线程)。有许多核心问题的变种如下:

  • 写线程不能处于饥饿状态(无限的等待他们执行的机会)
  • 读线程不能处于饥饿状态
  • 不应该有线程可以处于饥饿状态

多读/一写的互斥锁的具体实现(例如 sync.RWMutex)解决了读写问题的的其中之一。让我们看看这在Go总是如何做到的以及是它给到了一种到达什么样程度的保证。

作为一个奖励,我们深入的理解简化的竞争互斥锁。

使用方式

在深入到实现细节之前,让我们看看如何在实践中使用sync.RWMutex。如下的程序使用了读写互斥用来保护关键部分的操作—sleep()。通过对关键部分正在执行的读写线程进行计数来对整个程序执行过程的可视化(source code)。

package main
import (
    "fmt"
    "math/rand"
    "strings"
    "sync"
    "time"
)
func init() {
   
    rand.Seed(time.Now().Unix())
}
func sleep() {
   
    time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
}
func reader(c chan int, m *sync.RWMutex, wg *sync.WaitGroup) {
   
    sleep()
    m.RLock()
    c <- 1
    sleep()
    c <- -1
    m.RUnlock()
    wg.Done()
}
func writer(c chan int, m *sync.RWMutex, wg *sync.WaitGroup) {
   
    sleep()
    m.Lock()
    c <- 1
    sleep()
    c <- -1
    m.Unlock()
    wg.Done()
}
func main() {
   
    var m sync.RWMutex
    var rs, ws int
    rsCh := make(chan int)
    wsCh := make(chan int)
    go func() {
   
        for 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值