Golang之并发资源竞争(读写锁)
前面的有篇文章在讲资源竞争的时候,提到了互斥锁。互斥锁的根本就是当一个goroutine访问的时候,其他goroutine都不能访问,这样肯定保证了资源的同步,避免了竞争,不过也降低了性能。
仔细剖析我们的场景,当我们读取一个数据的时候,如果这个数据永远不会被修改,那么其实是不存在资源竞争的问题的。因为数据是不变的,不管怎么读取,多少goroutine同时读取,都是可以的。
所以其实读取并不是问题,问题主要是修改。修改的数据要同步,这样其他goroutine才可以感知到。所以真正的互斥应该是读取和修改、修改和修改之间,读取和读取是没有互斥操作的。
所以这就延伸出来另外一种锁,叫做读写锁。
读写锁可以让多个读操作同时并发,同时读取,但是对于写操作是完全互斥的。也就是说,当一个goroutine进行写操作的时候,其他goroutine既不能进行读操作,也不能进行写操作。
package main import (
"sync"
"fmt"
"math/rand"
)
var count int
var wg sync.WaitGroup
var rw sync.RWMutex func main() {
wg.Add()
for i:=;i<;i++ {
go read(i)
}
for i:=;i<;i++ {
go write(i)
}
wg.Wait()
} func read(n int) {
rw.RLock()
fmt.Printf("读goroutine %d 正在读取...\n",n)
v := count
fmt.Printf("读goroutine %d 读取结束,值为:%d\n", n,v)
wg.Done()
rw.RUnlock()
} func write(n int) {
rw.Lock()
fmt.Printf("写goroutine %d 正在写入...\n",n)
v := rand.Intn()
count = v
fmt.Printf("写goroutine %d 写入结束,新值为:%d\n", n,v)
wg.Done()
rw.Unlock()
}
我们在read里使用读锁,也就是RLock和RUnlock,写锁的方法名和我们平时使用的一样,是Lock和Unlock。这样,我们就使用了读写锁,可以并发地读,但是同时只能有一个写,并且写的时候不能进行读操作。现在我们再运行代码,可以从输出的数据看到,可以读到新值了。
我们同时也可以使用go build -race检测,也没有竞争提示了。
Golang之并发资源竞争(读写锁)的更多相关文章
- Golang之并发资源竞争(互斥锁)
并发本身并不复杂,但是因为有了资源竞争的问题,就使得我们开发出好的并发程序变得复杂起来,因为会引起很多莫名其妙的问题. package main import ( "fmt" &q ...
- Java并发编程之读写锁
读写锁维护了一对相关的锁,一个用于只读操作,一个用于写入操作.只要没有writer,读取锁可以由多个reader线程同时保持.写入锁是独占的. 可重入读写锁 ReentrantReadWriteLoc ...
- Java并发:ReadWriteLock 读写锁
读写锁在同一时刻可以允许多个线程访问,但是在写线程访问,所有的读线程和其他写线程均被阻塞. 读写锁不像 ReentrantLock 那些排它锁只允许在同一时刻只允许一个线程进行访问,读写锁可以允许多个 ...
- java并发锁ReentrantReadWriteLock读写锁源码分析
1.ReentrantReadWriterLock 基础 所谓读写锁,是对访问资源共享锁和排斥锁,一般的重入性语义为如果对资源加了写锁,其他线程无法再获得写锁与读锁,但是持有写锁的线程,可以对资源加读 ...
- [Go] 使用读写锁对map资源进行安全处理
当需要有一个全局性的map集合资源进行增删改数据时,需要对该map资源增加读写锁,防止并发时出现安全问题 下面的类就是举例 , 属性中的Conns模拟存储一些资源,对这些资源进行并发的增加数据,使用写 ...
- Java并发包源码学习系列:ReentrantReadWriteLock读写锁解析
目录 ReadWriteLock读写锁概述 读写锁案例 ReentrantReadWriteLock架构总览 Sync重要字段及内部类表示 写锁的获取 void lock() boolean writ ...
- Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁
相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...
- 三、curator recipes之共享的可重入读写锁
简介 curator实现了跨JVM的可重入读写互斥锁.它使用zookeeper去进行加锁,所以指定相同路径的处理线程将会基于“公平锁”的机制去竞争锁资源. 读写锁包含了读锁.写锁两个,它们的互斥关系如 ...
- 从火车站车次公示栏来学Java读写锁
Java多线程并发之读写锁 本文主要内容:读写锁的理论:通过生活中例子来理解读写锁:读写锁的代码演示:读写锁总结.通过理论(总结)-例子-代码-然后再次总结,这四个步骤来让大家对读写锁的深刻理解. 本 ...
随机推荐
- django drf 改变retrive的pk查询字段
lookup_filed可以改变retrive查询时默认以pk查询的逻辑 from django.shortcuts import render from rest_framework import ...
- Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH
TRY...CATCH使用范例 BEGIN TRY //逻辑语句块 END TRYBEGIN CATCH //Catch异常处理块 SET @msg = ERROR_MESSAGE(); PRINT ...
- layui json数据格式要求
layui 数据格式要求 layui有自己的一套特定的数据格式交互(这很重要),必须参数code:0,msg:“”,count:数据size(int),data:”数据List”.一般我们选择封装返 ...
- 文本相似度 余弦值相似度算法 VS L氏编辑距离(动态规划)
设置n为字符串s的长度.("我是个小仙女") 设置m为字符串t的长度.("我不是个小仙女") 如果n等于0,返回m并退出.如果m等于0,返回n并退出.构造两个向 ...
- docker 配置 overlay 存储
1.查看overlay模块是否安装 lsmod | grep over 2.将OverlayFS加到module目录下 echo "overlay" > /etc/modul ...
- 用TIdIPWatch获取本地IP
Indy的“indy misc”下有一个“TIdIPWatch”组件,可以正确获得本地IP,即使有多块网卡,也可以正确获得真正本地IP. 一,引入单元文件“IdIPWatch”. 二,实际代码: pr ...
- “全栈2019”Java第九十章:内部类可以向上或向下转型吗?
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- Working with Metal—Overview
看完这个 WWDC 之后的总结. Metal 可以在单位时间内提供 10 倍的 draw call 调用. Background About Draw Call 每一次 draw call 调用都必须 ...
- IIFE格式js写法
创建 加载文件方法 输出方法 方法书写 输出自定义变量 完整写法
- [原]时间格式化hh:mm:ss和HH:mm:ss区别
hh:mm:ss 按照12小时制的格式进行字符串格式化 如果时间处于00:00:00——12:59:59,则返回的字符串正常 如果时间处于13:00:00——23:59:59,则返回的字符串是实际 ...