Golang中互斥锁和读写互斥锁原理及示例代码
作者:周小末天天开心 发布时间:2024-05-29 22:06:52
互斥锁
在Golang中,互斥锁(Mutex)是一种基本的同步原语,用于实现对共享资源的互斥访问。互斥锁通过在代码中标记临界区来控制对共享资源的访问,从而保证同一时间只有一个 goroutine 可以访问共享资源,避免了并发访问时的数据竞争和不一致性问题。
互斥锁的主要方法包括两个,分别是 Lock 和 Unlock。Lock 方法用于锁定共享资源,防止其他 goroutine 访问;Unlock 方法则用于解锁共享资源,允许其他 goroutine 访问。一般来说,在使用互斥锁时,需要先通过 Lock 方法锁定共享资源,访问共享资源,然后再通过 Unlock 方法解锁共享资源,让其他 goroutine 可以访问。
使用互斥锁的示例代码
package main
import (
"fmt"
"sync"
)
var count int
var mutex sync.Mutex
func increment() {
mutex.Lock()
count++
mutex.Unlock()
wg.Done()
}
func main() {
for i := 0; i < 1000; i++ {
wg.Add(1)
go increment()
}
wg.Wait()
fmt.Println("Final count:", count)
}
在上面的示例代码中,increment函数是一个goroutine,它用来对count变量进行加1操作。在函数执行前通过mutex.Lock()获取互斥锁,在函数执行结束后通过mutex.Unlock()释放互斥锁。这样就保证了同一时刻只有一个goroutine可以访问count变量,从而避免了数据竞争的问题。
需要注意的是,在使用互斥锁时,一定要注意加锁和解锁的位置,否则可能会出现死锁的问题。
读写互斥锁
Go语言中的读写互斥锁(RWMutex)是一种特殊类型的互斥锁,它允许多个协程同时读取某个共享资源,但在写入时必须互斥,只能有一个协程进行写操作。相比互斥锁,读写互斥锁在高并发读的场景下可以提高并发性能,但在高并发写的场景下仍然存在性能瓶颈。
读写互斥锁有两个方法:RLock()和RUnlock()。在读取共享资源时,可以调用RLock()方法加读锁,在读取完成后,需要调用RUnlock()方法释放读锁。在写入共享资源时,需要调用Lock()方法加写锁,在写入完成后,需要调用Unlock()方法释放写锁。当有写锁或读写锁时,不能再加读锁或写锁,直到已经释放了所有锁。
读写互斥锁的示例代码
package main
import (
"fmt"
"sync"
"time"
)
var (
value int
rwLock sync.RWMutex
waitTime time.Duration = 100 * time.Millisecond
)
func readValue() {
rwLock.RLock()
defer rwLock.RUnlock()
time.Sleep(waitTime)
fmt.Println("Read value:", value)
}
func writeValue(val int) {
rwLock.Lock()
defer rwLock.Unlock()
time.Sleep(waitTime)
value = val
fmt.Println("Write value:", value)
}
func main() {
// 读操作可以并行执行
for i := 0; i < 5; i++ {
go readValue()
}
// 写操作必须等待读操作全部结束后才能执行
for i := 0; i < 5; i++ {
go writeValue(i)
}
// 等待所有goroutine执行完毕
time.Sleep(time.Second)
}
在这个示例中,使用了一个全局变量value来存储值,使用了一个sync.RWMutex类型的变量rwLock来保护这个变量的读写。在readValue函数中,首先调用RLock方法获取读锁,然后等待一段时间,最后输出变量value的值。在writeValue函数中,首先调用Lock方法获取写锁,然后等待一段时间,将传入的值赋给变量value,最后输出变量value的值。
在main函数中,首先启动5个goroutine来执行readValue函数,这些goroutine可以并行执行。然后启动5个goroutine来执行writeValue函数,这些goroutine必须等待所有的读操作完成后才能执行,因为它们需要获取写锁。
需要注意的是,在使用读写互斥锁时,必须保证写操作只有一个,否则就会出现竞争状态,导致数据不一致的问题。同时也需要注意使用锁的力度,避免锁的范围过大,导致性能下降。
来源:https://blog.csdn.net/weixin_71646897/article/details/130658711


猜你喜欢
- 环境:RHEL 5.4 x86 , oracle 11.2 1.设定环境变量 在/home/oracle编辑 # .bash_profile
- 前言Go语言做网络开发是非常容易的一件事,它已经为我们封装好了Http包,开箱即用。除此之外,我们也可以用Gin框架或者使用fasthttp
- 1、修改MD5算法重的4个常数,这是最捷径的作法,其特点是加密后的数据和加密前非常类似,但是不会被破解 2、多次加密,对MD5加密过的数据进
- SQL Server中包含多种不同类型的页,来满足数据存储的需求。不管是什么类型的页,它们的存储结构都是相同的。每个数据文件都包含相当数量的
- 冒泡排序:顾名思义就是(较小的值)像泡泡一样往上冒,(大的值)往下沉。实现原理:依次将相邻两个数值进行比较,较小的数值移到左边,较大的数值移
- 最近,找到了一种新的pycharm激活方法,支持Jetbrains全家桶,比如 idea、pychram、WebStorm等等,没得zhil
- 在最近工作中,有一个需求,需要做一个表格,并且对该表格右键弹出菜单支持增删改,这里做下总结,功能截图如下:首先定义菜单结构<!-- 菜
- 一、背景及研究现状在我国互联网的发展过程中,PC互联网已日趋饱和,移动互联网却呈现井喷式发展。数据显示,截止2013年底,中国手机网民超过5
- 背景:python函数库scipy的quad、dblquad实现一维二维积分的范例。需要注意dblquad的积分顺序问题。代码:import
- 本文实例为大家分享了Python使用Pillow添加水印的具体代码,供大家参考,具体内容如下python数据分析得到的图片,并对照片添加水印
- 我们都知道在9i之前,要想获得建表和索引的语句是一件很麻烦的事。我们可以通过export with rows=no来得到,但它的输出因为格式
- 这篇文章主要介绍了python智联招聘爬虫并导入到excel代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习
- 准备在以后制作的网站中尝试一些变化,比如:先提交内容,后提示注册/登陆。感觉这样可以绑架更多用户……不想注册再发言?那就先让你上钩发言,然后
- TF-IDFTF-IDF(Term Frequencey-Inverse Document Frequency)指词频-逆文档频率,它属于数
- 本文实例讲述了MySQL 多表关联一对多查询实现取最新一条数据的方法。分享给大家供大家参考,具体如下:MySQL 多表关联一对多查询取最新的
- 本文研究的主要是Django权限机制的相关内容,具体如下。1. Django权限机制概述权限机制能够约束用户行为,控制页面的显示内容,也能使
- 用Dreamweaver制作网页时,如果插入的图片、GIF动画、声音、视频或链接的网页是用中文命名的,在用IE浏览器浏览时可能显示不出来。以
- CSS中最常用的布局类属性,一个是Float(CSS浮动属性Float详解),另一个就是CSS定位属性Position。1. positio
- 什么是内存管理机制python中创建的对象的时候,首先会去申请内存地址,然后对对象进行初始化,所有对象都会维护在一个叫做refchain的双
- 一、http请求1、http请求方式:get和postget一般用于获取/查询资源信息,在浏览器中直接输入url+请求参数点击enter之后