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多线程并发之读写锁 本文主要内容:读写锁的理论:通过生活中例子来理解读写锁:读写锁的代码演示:读写锁总结.通过理论(总结)-例子-代码-然后再次总结,这四个步骤来让大家对读写锁的深刻理解. 本 ...
随机推荐
- mysql设定或修改密码的三个方法
为用户设定密码: 1.mysql>SET PASSWORD FOR 'USERNAME'@'HOST'=PASSWORD('password'); 2.# mysqladmin -uUSERNA ...
- hdu X问题 (中国剩余定理不互质)
http://acm.hdu.edu.cn/showproblem.php?pid=1573 X问题 Time Limit: 1000/1000 MS (Java/Others) Memory ...
- Spring Boot 学习系列(06)—采用log4j2记录日志
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 为什么选择log4j2 log4j2相比于log4j1.x和logback来说,具有更快的执行速度.同时也支 ...
- CentOS6.3上部署Ceph
一.背景知识 搭建ceph的机器分为两种:client和非client(mds.monitor.osd). 配置时client只需要在内核编译时选上ceph就行,而其它三种则还需要编译ceph用户态源 ...
- ansible 之条件语句 when
注册变量: 变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的playbook使用.例如: - hosts: webservers tasks: - shell: /usr/bin/foo ...
- 2018-2019-2 20165219《网络对抗技术》Exp2 后门原理与实践
2018-2019-2 20165219<网络对抗技术>Exp2 后门原理与实践 实验内容 使用netcat获取主机操作Shell,cron启动 使用Socat获取主机操作Shell, 任 ...
- Problem H: 小姐姐的QQ号(DFS)
Contest - 河南省多校连萌(四) Problem H: 小姐姐的QQ号 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 297 Solved: ...
- Java io流完成复制粘贴功能
JAVA 中io字节输入输出流 完成复制粘贴功能: public static void main(String[] args) throws Exception{ // 创建输入流要读 ...
- setInterval(),setTimeout(),location.reload(true)
1,setInterval() setInterval()方法可以按照指定的周期来调用函数或表达式,他会不停地调用函数,直到调用clearInterval()方法或窗口关闭.由setInterval( ...
- [Objective-C语言教程]Posing(29)
Posing,顾名思义,意思是“冒充”,它跟categories类似,但本质上不一样,Posing存在的目的在于子类可以冒充父类,使得后续的代码无需把父类修改为子类,就可以很方便的让父类表现成子类的行 ...