当前位置:网站首页>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
边栏推荐
- SQL编程问题,测试用例不通过
- Deep understanding Net (2) kernel mode 2 Kernel mode construct semaphone
- Directory related commands
- 【 scientific literature measurement 】 mining and visualization of keywords in foreign and Chinese Literature
- Google Earth Engine(GEE)——将字符串的转化为数字并且应用于时间搜索( ee.Date.fromYMD)
- [scientific research data processing] [practice] frequency analysis chart of category variables, distribution chart of numerical variables and normality test (including lognormal)
- Prometheus 2.29.0 new features
- Why does the folder appear open in another program
- Pytoch viewing model parameter quantity and calculation quantity
- Yousi College: Six Sigma is not just statistics!
猜你喜欢

The programming competition is coming! B station surrounding, senior members and other good gifts to you!

编程实战赛来啦!B站周边、高级会员等好礼送你啦!

“即服务”,企业数字化转型的必然选择

损失函数:DIOU loss手写实现

Mysql database foundation: stored procedures and functions

Waving flags and shouting for basic language
![[redis series] redis learning 16. Redis Dictionary (map) and its core coding structure](/img/5a/5da6180db0b2b96660bcd9b4fa0633.png)
[redis series] redis learning 16. Redis Dictionary (map) and its core coding structure

How can I protect my private key?

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

【科学文献计量】外文文献及中文文献关键词的挖掘与可视化
随机推荐
Golang template (text/template)
【科学文献计量】外文文献及中文文献关键词的挖掘与可视化
用Unity实现Flat Shading
目录相关命令
[scientific research data processing] [practice] frequency analysis chart of category variables, distribution chart of numerical variables and normality test (including lognormal)
I want to ask how to open an account at China Merchants Securities? Is it safe to open a stock account through the link
Numpy creates an empty array data = np empty(shape=[1, 64,64,3])
How can I protect my private key?
Why can't the database table be written into data
IM即时通讯应用开发中无法解决的“顽疾”
华为帐号多端协同,打造美好互联生活
In the digital age, XDR (extended detection and response) has unlimited possibilities
Apache Doris comparison optimization Encyclopedia
数据库表为什么写不进数据了
[kubernetes series] k8s set mysql8 case insensitive
科普达人丨漫画图解什么是eRDMA?
MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video
[Title brushing] coco, who likes bananas
Observable, reliable: the first shot of cloudops series Salon of cloud automation operation and maintenance
MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video