
Golang互斥锁和读写锁的性能差异
发布日期:2021-05-06 23:58:27
浏览次数:18
分类:精选文章
本文共 2122 字,大约阅读时间需要 7 分钟。
1.互斥锁
互斥锁是一种常用的控制共享资源访问的方法,它能够保证同时只有一个goroutine
可以访问共享资源。Go语言中使用sync
包的Mutex
类型来实现互斥锁。 使用互斥锁来修复上面代码的问题:
var x int64var wg sync.WaitGroupvar lock sync.Mutexfunc add() { for i := 0; i < 5000; i++ { lock.Lock() // 加锁 x = x + 1 lock.Unlock() // 解锁 } wg.Done()}func main() { wg.Add(2) go add() go add() wg.Wait() fmt.Println(x)}
结果永远是10000。 对公共资源操作时,应该加锁
使用互斥锁能够保证同一时间有且只有一个goroutine
进入临界区,其他的goroutine
则在等待锁;当互斥锁释放后,等待的goroutine
才可以获取锁进入临界区,多个goroutine
同时等待一个锁时,唤醒的策略是随机的。
模拟读多写少的一个场景
var ( x = 0 wg sync.WaitGroup lock sync.Mutex)func read () { defer wg.Done() lock.Lock() fmt.Println(x) time.Sleep(time.Millisecond) 读需要1毫秒 lock.Unlock()}func write() { defer wg.Done() lock.Lock() x ++ lock.Unlock() time.Sleep(time.Millisecond * 5) 写需要5毫秒}func main() { start := time.Now() for i:= 0; i<10 ; i++ { go write() wg.Add(1) } for i:= 0; i<1000 ; i++ { go read() wg.Add(1) } wg.Wait() fmt.Println(time.Since(start)) 15.516195s}
互斥锁,在读的时候,也会阻塞下一个读线程,这样效率很低。
2.读写互斥锁
普通锁是 sync.Mutex
读写锁是 sync.RWMutex互斥锁是完全互斥的,但是有很多实际的场景下是读多写少的,当我们并发的去读取一个资源不涉及资源修改的时候是没有必要加锁的,这种场景下使用读写锁是更好的一种选择。读写锁在Go语言中使用sync
包中的RWMutex
类型。
读写锁分为两种:读锁和写锁。当一个goroutine获取读锁之后,其他的goroutine
如果是获取读锁会继续获得锁,如果是获取写锁就会等待;当一个goroutine
获取写锁之后,其他的goroutine
无论是获取读锁还是写锁都会等待。
RWMutex提供了四个方法:
func (*RWMutex) Lock // 写锁定
func (*RWMutex) Unlock // 写解锁
func (*RWMutex) RLock // 读锁定
func (*RWMutex) RUnlock // 读解锁
读写锁示例:
var ( x = 0 wg sync.WaitGroup lock sync.RWMutex)func read () { defer wg.Done() lock.RLock() 加读锁 fmt.Println(x) time.Sleep(time.Millisecond) lock.RUnlock() 解读锁}func write() { defer wg.Done() 加写锁 lock.Lock() x ++ lock.Unlock() 解写锁 time.Sleep(time.Millisecond * 5)}func main() { start := time.Now() for i:= 0; i<10 ; i++ { go write() wg.Add(1) } for i:= 0; i<1000 ; i++ { go read() wg.Add(1) } wg.Wait() fmt.Println(time.Since(start)) 20.0658ms,速度和互斥锁差别非常大}
需要注意的是读写锁非常适合读多写少的场景,如果读和写的操作差别不大,读写锁的优势就发挥不出来。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月07日 13时01分09秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
数据结构之数组与经典面试题(二)
2021-05-08
无锁并发框架-Disruptor的使用(二)
2021-05-08
Android wm命令
2021-05-08
boot.img 解包与打包
2021-05-08
Android4.4 平板背光设置
2021-05-08
spring boot@Value和bean执行顺序问题
2021-05-08
codeforces The Eternal Immortality 题解
2021-05-08
蓝桥杯 历届试题 幸运数 (堆+DFS)
2021-05-08
微信js-sdk使用简述(分享,扫码功能等)
2021-05-08
selenium 的介绍和爬取 jd数据
2021-05-08
【分享-一键在线抠图】在线免费去除图片背景
2021-05-08
layui表格checkbox选择全选样式及功能
2021-05-08
mxsrvs支持thinkphp3.2伪静态
2021-05-08
mui HTML5 plus 下载文件
2021-05-08
环信SDK 踩坑记webIM篇(一)
2021-05-08
通信基础知识
2021-05-08
DSP开发板准备
2021-05-08
测试基本
2021-05-08
c++中istringstream及ostringstream超详细说明
2021-05-08