iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang并发操作中常见的读写锁详析
  • 834
分享到

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

2024-04-02 19:04:59 834人浏览 泡泡鱼
摘要

互斥锁简单粗暴,谁拿到谁操作。今天给大家介绍一下读写锁,读写锁比互斥锁略微复杂一些,不过我相信我们今天能够把他拿下! 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()就是执行读写锁的读模式,执行这个模式其他协程也能读,但是都不能写。

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

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

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

Golang读写锁底层原理

在加读锁和写锁的工程中都使用atomic.AddInt32来进行递增,而该指令在底层是会通过LOCK来进行CPU总线加锁的,因此多个CPU同时执行readerCount其实只会有一个成功,从这上面看其实是写锁与读锁之间是相对公平的,谁先达到谁先被CPU调度执行,进行LOCK锁cache line成功,谁就加成功锁

底层实现的CPU指令

底层的2条指令,通过LOCK指令配合CPU的MESI协议,实现可见性和内存屏障,同时通过XADDL则用来保证原子性,从而解决可见性与原子性问题


// atomic/asm_amd64.s TEXT runtime∕internal∕atomic·Xadd(SB)
    LOCK
    XADDL   AX, 0(BX)

可见性与内存屏障、原子性, 其中可见性通常是指在cpu多级缓存下如何保证缓存的一致性,即在一个CPU上修改了了某个数据在其他的CPU上不会继续读取旧的数据,内存屏障通常是为了CPU为了提高流水线性能,而对指令进行重排序而来,而原子性则是指的执行某个操作的过程的不可分割

总结

到此这篇关于golang并发操作中常见读写锁的文章就介绍到这了,更多相关Golang并发读写锁内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Golang并发操作中常见的读写锁详析

本文链接: https://www.lsjlt.com/news/133896.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Golang并发操作中常见的读写锁详析
    互斥锁简单粗暴,谁拿到谁操作。今天给大家介绍一下读写锁,读写锁比互斥锁略微复杂一些,不过我相信我们今天能够把他拿下! golang读写锁,其特征在于 读锁:可以同时进行多个...
    99+
    2024-04-02
  • 详解Golang并发操作中常见的死锁情形
    目录第一种情形:无缓存能力的管道,自己写完自己读 第二种情形:协程来晚了 第三种情形:管道读写时,相互要求对方先读/写 第四种情形:读写锁相互阻塞,形成隐形死锁 什么是死锁,在Go的...
    99+
    2024-04-02
  • golang并发安全及读写互斥锁的示例分析
    目录并发安全和锁互斥锁读写互斥锁并发安全和锁 有时候在Go代码中可能会存在多个goroutine同时操作一个资源(临界区),这种情况会发生竞态问题(数据竞态)。类比现实生活中的例子有...
    99+
    2024-04-02
  • Golang中常见的并发编程模式详解
    Golang中常见的并发编程模式详解 随着软件开发行业的不断发展,对高性能和高并发的需求也越来越迫切。并发编程已经成为现代软件开发中不可或缺的一部分,而Golang(Go语言)作为一种...
    99+
    2024-02-28
    模式 golang 并发 go语言
  • Java 并发包中的读写锁及其实现分析
    这期内容当中小编将会给大家带来有关Java 并发包中的读写锁及其实现分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. 前言在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他...
    99+
    2023-06-17
  • 解析golang中的并发安全和锁问题
    1. 并发安全 package main import ( "fmt" "sync" ) var ( sum int wg sync.Wa...
    99+
    2024-04-02
  • Java中常见的并发控制手段浅析
    目录前言1.1 同步代码块1.2 CAS自旋方式1.3 锁1.4 阻塞队列1.5 信号量Semaphore1.6 计数器CountDownLatch1.7 栅栏 CyclicBarr...
    99+
    2024-04-02
  • python中字典的常见操作实例分析
    这篇文章主要介绍了python中字典的常见操作实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python中字典的常见操作实例分析文章都会有所收获,下面我们一起来看看吧。python中字典的常见操作字典添...
    99+
    2023-07-02
  • 如何在 Python 中进行文件读写操作?详细解析!
    Python 是一门强大的编程语言,它不仅可以用于数据分析、机器学习等领域,还可以用来处理文件读写操作。在本文中,我们将详细介绍如何在 Python 中进行文件读写操作,并且提供一些有用的代码示例。 文件的读取操作 在 Python 中,我...
    99+
    2023-06-28
    关键字 编程算法 文件
  • Java学习笔记:如何解决Load并发操作中的常见问题?
    在Java开发中,Load并发操作是非常常见的一种操作。然而,由于并发操作的特殊性质,很容易出现一些常见的问题。在本文中,我们将介绍一些常见的Load并发操作问题,并提供一些解决方案和演示代码。 线程安全问题 在并发操作中,线程安全是...
    99+
    2023-09-09
    学习笔记 load 并发
  • 分析Golang中map的删除操作详解
    在Golang中,map(映射)是一种非常常用的数据结构,用于存储键值对。在使用map的过程中,涉及到对map进行删除操作是非常重要的,因为错误的删除操作可能会导致内存泄漏或者程序运行...
    99+
    2024-02-24
    删除 golang map 键值对
  • Android编程中File文件常见存储与读取操作的示例分析
    这篇文章给大家分享的是有关Android编程中File文件常见存储与读取操作的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体如下:MainActivity文件代码如下:package exa...
    99+
    2023-05-30
    android file
  • golang函数并发控制中常见的错误与陷阱
    并发错误和陷阱:错误1:データ競合:多个例程同时修改共享数据。错误2:デッドロック:两个以上例程互相等待,无限阻塞。错误3:チャネルの誤用:チャネルの早期クローズや、クローズしたチャネル...
    99+
    2024-04-24
    并发控制 陷阱 golang
  • js中DOM事件常见操作的示例分析
    这篇文章主要介绍js中DOM事件常见操作的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、JavaScript的组成JavaScript基础分为三个部分:ECMAScrip...
    99+
    2024-04-02
  • Golang中除法操作的常见错误及解决方法
    Golang中除法操作的常见错误及解决方法 在Golang中,除法操作是我们在日常编程中经常会遇到的运算之一。然而,有时候在进行除法操作的过程中,我们可能会遇到一些常见的错误,这些错误...
    99+
    2024-02-22
    错误 golang 除法
  • PHP并发编程中,如何有效处理文件和日志的读写操作?
    在PHP并发编程中,文件和日志的读写操作是非常常见的。然而,它们的处理方式会对系统性能产生很大的影响。本文将介绍如何在PHP并发编程中有效处理文件和日志的读写操作。 文件读写 在PHP中,文件读写是通过文件指针来实现的。我们可以使用fop...
    99+
    2023-06-09
    并发 文件 日志
  • golang中一种不常见的switch语句写法示例详解
    最近翻开源代码的时候看到了一种很有意思的switch用法,分享一下。 注意这里讨论的不是typed switch,也就是case语句后面是类型的那种。 直接看代码: func (s ...
    99+
    2023-05-18
    golang switch语句写法 golang switch写法
  • Java学习笔记:如何在Load并发操作中避免常见错误?
    在Java中,Load并发操作是非常常见的操作,它可以有效地提高程序的性能和响应速度。然而,由于并发操作涉及到多个线程同时访问共享资源,因此容易出现一些常见的错误。在这篇文章中,我们将介绍如何在Load并发操作中避免常见错误,并提供一些演...
    99+
    2023-09-09
    学习笔记 load 并发
  • java中volatile变量并发操作的示例分析
    小编给大家分享一下java中volatile变量并发操作的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java的特点有哪些Java的特点有哪些1.Jav...
    99+
    2023-06-14
  • Java开发中,如何避免文件读写出现的常见问题?
    Java开发中,文件读写是常见的操作之一。然而,由于各种原因,文件读写可能会出现一些常见问题。这些问题可能会导致数据损坏,程序崩溃等严重后果。因此,在Java开发中,我们需要特别注意文件读写操作,并采取一些措施来避免常见问题的出现。 本文将...
    99+
    2023-09-12
    关键字 开发技术 文件
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作