当前位置:网站首页>Go common lock mutex and rwmutex
Go common lock mutex and rwmutex
2022-06-30 14:09:00 【Zhen Jie.】
go Medium sync Two kinds of locks in :
Mutex: The mutex sync.Mutex
RWMutex: Read-write lock , The underlying dependence Mutex Realization sync.RWMutex
The mutex (Mutex)
Mutex structure :
type Mutex struct {
state int32
sema uint32
}
Mutex It's a mutex , Fields that can be created as other structures ; Zero is the unlocked state .Mutex Type of lock is thread independent , It can be locked and unlocked by different threads .
type UserInfo struct {
Name string
Age int
sync.Mutex
}
func (userInfo *UserInfo) updateUserInfo(name string, age int) {
userInfo.Lock()
defer userInfo.Unlock()
userInfo.Name = name
userInfo.Age = age
}
Lock status value is 1, Unlocked state lock not 0
func main() {
userInfo := UserInfo{
Name: "text1", Age: 20}
fmt.Println(userInfo)
userInfo.Lock()
fmt.Println(userInfo)
}
Lock() Lock 、Unlock Unlock
func main() {
mutex := sync.Mutex{
}
mutex.Lock()
mutex.Unlock()
}
When one goroutine After obtaining the mutex , other goroutine Cannot use locked resources , Can only wait for resources to be released
func main() {
userInfo := UserInfo{
Name: "test1"}
go userInfo.read(1)
go userInfo.read(2)
time.Sleep(time.Second*2)
}
func (userInfo *UserInfo) read(n int) {
fmt.Println(n)
fmt.Println(n)
fmt.Println(n)
}
Running results ( It is not unique but there may be many staggered operation certificates goroutine Use ):
1
2
2
2
1
1
Let's modify the code. In order to make you better see the effect, I specially added sleep :
type UserInfo struct {
Name string
sync.Mutex
}
func main() {
userInfo := UserInfo{
Name: "test1"}
go userInfo.read1(1)
go userInfo.read2(2)
time.Sleep(time.Second * 2)
}
func (userInfo *UserInfo) read1(n int) {
defer userInfo.Unlock()
userInfo.Lock()
time.Sleep(time.Second)
fmt.Println(n)
fmt.Println(n)
fmt.Println(n)
}
func (userInfo *UserInfo) read2(n int) {
defer userInfo.Unlock()
userInfo.Lock()
fmt.Println(n)
fmt.Println(n)
fmt.Println(n)
}
Running results :
1
1
1
2
2
2
It turns out that 1,1,1 - 2,2,2 perhaps 2,2,2 -1,1,1 Both, depending on who locks the resource
Do not reuse the same resource Lock(), Must wait Unlock() And then again Lock(), Otherwise, it will cause deadlock
type UserInfo struct {
Name string
sync.Mutex
}
func main() {
userInfo := UserInfo{
Name: "test1"}
userInfo.Lock()
userInfo.Lock()
}
fatal error: all goroutines are asleep - deadlock!
For not being Lock() The use of resources Unlock It can lead to panic abnormal
type UserInfo struct {
Name string
sync.Mutex
}
func main() {
userInfo := UserInfo{
Name: "test1"}
userInfo.Unlock()
}
fatal error: sync: unlock of unlocked mutex
Locked Mutex Not related to a particular goroutine Related to , This can take advantage of a goroutine Lock it , Taking advantage of other goroutine Unlock it
type UserInfo struct {
Name string
sync.Mutex
}
func main() {
userInfo := UserInfo{
Name: "test1"}
go func() {
userInfo.Lock()
userInfo.Name = "test2"
go func() {
userInfo.Unlock()
}()
}()
time.Sleep(time.Second)
fmt.Print(userInfo)
}
{
test2 {
0 0}}
Process finished with exit code 0
You can see in another goroutine Unlocked in
After removing the unlock, you can see that the print result is still locked
type UserInfo struct {
Name string
sync.Mutex
}
func main() {
userInfo := UserInfo{
Name: "test1"}
go func() {
userInfo.Lock()
userInfo.Name = "test2"
}()
time.Sleep(time.Second)
fmt.Print(userInfo)
}
{
test2 {
1 0}}
Process finished with exit code 0
notes : stay goroutine (g1) Middle lock , And then others goroutine (g2) Can be unlocked in , But when g1 Unlocking again will panic
func main() {
var mu sync.Mutex
go func() {
mu.Lock()
time.Sleep(10 * time.Second)
mu.Unlock()
}()
time.Sleep(time.Second)
mu.Unlock()
select {
}
}
Suitable for reading and writing uncertainty , And there is only one reading or writing scene That is, the use scenario of pessimistic locks
Read-write lock (RWMutex)
structure :
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // semaphore for writers to wait for completing readers
readerSem uint32 // semaphore for readers to wait for completing writers
readerCount int32 // number of pending readers
readerWait int32 // number of departing readers
}
type UserInfo struct {
Name string
sync.RWMutex
}
The following examples use the above test structure by default unless otherwise specified
RWMutex It's a single write multiple read lock , The lock can add multiple read locks or one write lock
func main() {
userInfo := UserInfo{
Name: "test1"}
go userInfo.read0()
go userInfo.read1()
time.Sleep(time.Second * 2)
}
func (userInfo *UserInfo) read0() {
defer userInfo.Unlock()
userInfo.Lock()
fmt.Println(1)
time.Sleep(time.Second)
fmt.Println(1)
fmt.Println(1)
}
func (userInfo *UserInfo) read1() {
userInfo.RLock()
fmt.Println(2)
fmt.Println(2)
fmt.Println(2)
}
result :
1
1
1
2
2
2
When the write lock is involved, it is followed by Mutex similar
Read lock occupancy prevents writing , Won't stop reading , Multiple goroutine Read locks can be acquired at the same time
func main() {
userInfo := UserInfo{
Name: "test1"}
go userInfo.read0()
go userInfo.read1()
time.Sleep(time.Second * 2)
}
func (userInfo *UserInfo) read0() {
userInfo.RLock()
fmt.Println(1)
time.Sleep(time.Second)
fmt.Println(1)
fmt.Println(1)
}
func (userInfo *UserInfo) read1() {
userInfo.RLock()
fmt.Println(2)
fmt.Println(2)
fmt.Println(2)
}
result :
2
2
2
1
1
1
Writing locks will prevent other gorotine Whether it's read or written , The entire lock consists of a write lock goroutine Occupy Share the demo code with the first one
It is suitable for reading more and writing less
RWMutex Of Lock() and Unlock()
Lock() Add write lock ,Unlock() Unlock the lock
If there are other read and write locks before adding write locks , be Lock() Will block until the lock is available , To ensure that the lock is available , Already blocked Lock() The call excludes the new reader from the acquired lock , That is, the write lock permission is higher than the read lock permission , When there is a write lock, priority is given to write lock
func main() {
userInfo := UserInfo{
Name: "test1"}
go userInfo.userRLock()
go userInfo.userRLock()
go userInfo.userRLock()
go userInfo.userRLock()
go userInfo.userLock()
time.Sleep(time.Second*5)
}
func (userInfo *UserInfo) userLock() {
defer userInfo.Unlock()
userInfo.Lock()
fmt.Println("lock")
fmt.Println("lock")
fmt.Println("lock")
}
func (userInfo *UserInfo) userRLock() {
defer userInfo.RUnlock()
userInfo.RLock()
time.Sleep(time.Second)
fmt.Println("Rlock")
fmt.Println("Rlock")
fmt.Println("Rlock")
}
result :
Rlock
Rlock
Rlock
Rlock
Rlock
Rlock
lock
lock
lock
Rlock
Rlock
Rlock
Rlock
Rlock
Rlock
You can see that in most cases lock Priority is higher than Rlock Of
stay Lock() Before using Unlock() It can lead to panic abnormal
Rlock() and RUnlock()
Rlock() Add read lock ,Runlock() Interpreting locks
func main() {
userInfo := UserInfo{
Name: "test1"}
userInfo.RLock()
userInfo.RUnlock()
}
RLock() When reading lock , If there is a write lock , Can not be read ; When there is only a read lock or no lock , You can add a read lock , The read lock can be loaded with multiple locks that are opposite to the second write lock
Rulock() Interpreting locks ,RUnlock revoke RLock() call , It has no effect on other simultaneous read locks
Call... Without reading the lock Runlock() It can lead to panic error
func main() {
userInfo := UserInfo{
Name: "test1"}
userInfo.RUnlock()
}
fatal error: sync: RUnlock of unlocked RWMutex
stay RUnlock() The number of must not be excessive RLock(), Otherwise, it will lead to panic error
func main() {
userInfo := UserInfo{
Name: "test1"}
userInfo.RLock()
userInfo.RUnlock()
userInfo.RUnlock()
}
fatal error: sync: RUnlock of unlocked RWMutex
边栏推荐
- Flat shading with unity
- 【刷题篇】爱吃香蕉的珂珂
- 提权扫描工具
- Observable, seulement fiable: première bombe de salon de la série cloudops d'exploitation et d'entretien automatisés dans le nuage
- Prometheus 2.29.0 new features
- Unity Animator 参数
- DNS 解析之家庭网络接入 Public DNS 实战
- 可觀測,才可靠:雲上自動化運維CloudOps系列沙龍 第一彈
- MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video
- Impersonate server and client using message queuing
猜你喜欢

Lifting scanning tool

Google Earth engine (GEE) - ghsl: global human settlements layer, built grid 1975-1990-2000-2015 (p2016) data set

Google Earth engine (GEE) -- converts string to number and applies it to time search (ee.date.fromymd)
![[deep anatomy of C language] storage principle of float variable in memory & comparison between pointer variable and](/img/3d/5d7fafba4ff7903afbd51d6d58dcdf.png)
[deep anatomy of C language] storage principle of float variable in memory & comparison between pointer variable and "zero value"

Observable, reliable: the first shot of cloudops series Salon of cloud automation operation and maintenance

Jetpack Compose 实现完美屏幕适配

深入理解.Net中的线程同步之构造模式(二)内核模式2.内核模式构造物Semaphone

This editor will open source soon!

Jetpack compose for perfect screen fit

How to execute a query SQL
随机推荐
可觀測,才可靠:雲上自動化運維CloudOps系列沙龍 第一彈
“即服务”,企业数字化转型的必然选择
第四批入围企业公示——年度TOP100智能网联供应商评选
In the digital age, XDR (extended detection and response) has unlimited possibilities
Pytorch查看模型参数量和计算量
Intelligent operation and maintenance: visual management system based on BIM Technology
Complete TCP forwarding server (kernel linked list + mutex)
Waving flags and shouting for basic language
Google Earth Engine(GEE)——GHSL:全球人类住区层,建成网格 1975-1990-2000-2015 (P2016) 数据集
深入理解.Net中的线程同步之构造模式(二)内核模式4.内核模式构造物的总结
Begin End use the pit encountered
DeFi“钱从哪来”?一个大多数人都没搞清楚的问题
Click the TD cell of table to open the dialog pop-up window. After obtaining the value, put the value back into the TD cell
正则系列之断言Assertions
单元测试效率优化:为什么要对程序进行测试?测试有什么好处?
Inexplicable error occurred in unity's frequent switching branch result model
Shell programming overview
Observable, seulement fiable: première bombe de salon de la série cloudops d'exploitation et d'entretien automatisés dans le nuage
[the path of system analyst] Chapter V software engineering (software process improvement)
[Title brushing] avoid flooding