Golang:并发操作中常见的读写锁

举报
Regan Yue 发表于 2021/08/29 09:48:46 2021/08/29
1.8k+ 0 1
【摘要】 Golang:并发操作中常见的读写锁互斥锁简单粗暴,谁拿到谁操作。今天给大家介绍一下读写锁,读写锁比互斥锁略微复杂一些,不过我相信我们今天能够把他拿下!读写锁有两种模式。没错!一种是读模式,一种是写模式。当他为写模式的话,作用和互斥锁差不多,只允许有一个协程抢到这把锁,其他协程乖乖排队。但是读模式就不一样了,他允许你多个协程读,但是不能写。总结起来就是:仅读模式: 多协程可读不可写仅写模式...

Golang:并发操作中常见的读写锁

互斥锁简单粗暴,谁拿到谁操作。今天给大家介绍一下读写锁,读写锁比互斥锁略微复杂一些,不过我相信我们今天能够把他拿下!

读写锁有两种模式。没错!一种是读模式,一种是写模式。当他为写模式的话,作用和互斥锁差不多,只允许有一个协程抢到这把锁,其他协程乖乖排队。但是读模式就不一样了,他允许你多个协程读,但是不能写。总结起来就是:

  • 仅读模式: 多协程可读不可写
  • 仅写模式: 单协程可写不可读

在32位的操作系统中,针对int64类型的值的读和写操作都不可能仅由一个CPU指令来完成。如若一个写操作刚刚执行完第一个指令,就去进行另一个读的协程,这样就会读到一个错误的数据。

下面看个例子吧:

先看主函数:

func main() {
	for i:=0;i<5;i++{
		wg06.Add(1)
		go write(i)

		wg06.Add(1)
		go read(i)
	}
    wg06.Wait()
}

每次开辟两条协程,一条协程执行写函数,另一条执行读函数。然后放入等待组。共开辟五次。

在来看一看写函数

func write(i int)  {
	//锁定为仅写模式,其他协程被阻塞
	rwm.Lock()

	fmt.Println(i,"writing...")
	<- time.After(10*time.Second)
	fmt.Println("write over!")

	rwm.Unlock()
	//解锁仅写模式
	wg06.Done()
}

这个Lock()就是执行读写锁的写模式,当这个模式进行时,只有这条协程能写,其他协程都被阻塞。Unlock()就是解锁这个仅锁模式,等待组中的其他协程不再被阻塞。

再看一看读模式:

func read(i int)  {
	rwm.RLock()

	fmt.Println(i,"reading...")
	<-time.After(10 * time.Second)
	fmt.Println(i,"read over!")

	rwm.RUnlock()
	wg06.Done()
}

RLock()就是执行读写锁的读模式,执行这个模式其他协程也能读,但是都不能写。

如果程序运行,写协程先抢到锁,所有协程就不能读,只有这条写协程能写,其他人都等着。如果是读协程抢到锁,所以写协程就不可能了,但是读协程仍然可以抢。

现在你知道我们应该什么时候使用读写锁了吗?

在并发进行读写操作时,当读的次数远远超过写的次数的情况下,应该使用读写锁来进行读写并发操作。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。