美文网首页go并发编程
Go并发编程之美-读写锁

Go并发编程之美-读写锁

作者: 阿里加多 | 来源:发表于2019-02-13 09:02 被阅读18次

一、前言

go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中读写锁

二、读写锁

go中读写锁,在没有线程获取写锁情况下多个线程可以同时获取读锁,读锁是可重入锁,写锁则是互斥锁(不可重入)。

package main

import (
    "fmt"
    "sync"
    "time"
)

var (
    counter int            //计数器
    wg      sync.WaitGroup //信号量
    lock    sync.RWMutex   //读写锁
)

func main() {

    //1.两个信号
    wg.Add(1)

    //2.获取读锁
    fmt.Println("main thread wait rlock")
    lock.RLock()
    fmt.Println("main thread got rlock")
    //3.开启子线程
    go incCounter()
    fmt.Println(counter)
    time.Sleep(time.Second * 5)
    //4.释放读锁
    lock.RUnlock()
    fmt.Println("main thread release rlock")

    //5.等待子线程结束
    wg.Wait()
    fmt.Println(counter)

}

func incCounter() {
    defer wg.Done()

    //2.1.获取锁
    fmt.Println("sub thread wait rlock")
    lock.Lock()
    fmt.Println("sub thread got rlock")

    //2.2.计数加1
    counter++

    //2.3.释放独占锁
    lock.Unlock()
    fmt.Println("sub thread relese rlock")

}

  • 如上代码go中使用sync.RWMutex可以获取一个开箱即用的读写锁
  • 代码(2)主线程使用lock.RLock()获取读锁,然后开启了子线程(代码3),然后在主线程持有读锁的情况下休眠了5s后释放了锁。
  • 子线程在代码2.1尝试使用 lock.Lock()获取写锁,由于主线程还没释放读锁,所以子线程阻塞到了这里,直到主线程休眠后执行代码4释放了读锁。
  • 执行代码会输出:
main thread wait rlock
main thread got rlock
0
sub thread wait rlock
main thread release rlock
sub thread got rlock
sub thread relese rlock
1

这个例子说明了,当有线程获取了读锁并没释放时候,获取写锁的线程要等待。

另外使用下面方法可以验证读锁是可重入锁:

    lock.RLock()
    lock.RLock()
    fmt.Println(counter)
    lock.RUnlock()
    lock.RUnlock()

使用下面代码可以验证同一个线程的读锁,不能晋升为写锁:

    lock.RLock()
    lock.Lock()
    fmt.Println(counter)
    lock.Unlock()
    lock.RUnlock()

上面代码执行会报错:


image.png

三、总结

go中读写锁中的读锁是可重入共享锁,写锁是互斥锁,读锁不能晋升为写锁。

相关文章

  • Go并发编程之美-读写锁

    一、前言 go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CA...

  • Go并发编程之美-互斥锁

    一、前言 go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CA...

  • Go语言高并发Map解决方案

    Go语言高并发Map解决方案 Go语言基础库中的map不是并发安全的,不过基于读写锁可以实现线程安全;不过在Go1...

  • GO语言并发编程之互斥锁、读写锁详解

    一、互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段。它由标准库代码包sync中的Mutex结构体类...

  • Go 并发之读写锁

    在业务当中我们常常需要遇到并发读写,其中读的频率远大于写的频率的情况,对数据的写入是需要互斥的,也就是同时只能允许...

  • 并发编程之——读锁源码分析(解释关于锁降级的争议)

    1. 前言 在前面的文章 并发编程之——写锁源码分析中,我们分析了 1.8 JUC 中读写锁中的写锁的获取和释放过...

  • golang 基础(31) 锁

    在 go 语言中提供了并发编程模型和工具外,还提供传统的同步工具锁,包括互斥锁和读写锁有关互斥锁有些内容我们必须清...

  • Go 语言的锁

    Go 语言提供两类锁: 互斥锁(Mutex)和读写锁(RWMutex)。其中读写锁(RWMutex)是基于互斥锁(...

  • 1.MySQL的架构与历史

    MySQL逻辑架构 并发控制 读写锁sharelock共享锁,exclusivelock排他锁 锁粒度table ...

  • go并发编程之美(一)

    一、前言 在Java中多线程之间是通过共享内存进行通信的,在go中多线程之间通信是基于消息的,go中的通道是go中...

网友评论

    本文标题:Go并发编程之美-读写锁

    本文链接:https://www.haomeiwen.com/subject/hwuheqtx.html