当前位置:网站首页>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
边栏推荐
- 为基础性语言摇旗呐喊
- Prometheus 2.29.0 new features
- Comprehensively analyze the basic features and summary of free and paid SSH tools
- Je suis à Foshan, où puis - je ouvrir un compte? L'ouverture d'un compte par téléphone mobile est - elle sécurisée?
- 深入理解.Net中的线程同步之构造模式(二)内核模式4.内核模式构造物的总结
- 点击table的td单元格出现dialog弹窗,获取值后将值放回td单元格
- Impersonate server and client using message queuing
- 数字时代,XDR(扩展检测与响应)的无限可能
- [Title brushing] coco, who likes bananas
- Solve the error in my QT_ thread_ global_ End(): 3 threads didn't exit
猜你喜欢

MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video

Loss function: Diou loss handwriting implementation

重磅:国产IDE发布,由阿里研发,完全开源!

可觀測,才可靠:雲上自動化運維CloudOps系列沙龍 第一彈

SQL attendance statistics monthly report

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

"Persistent diseases" that cannot be solved in IM application development
![[Title brushing] coco, who likes bananas](/img/66/5646ac7e644025ccaee7c17f62ce17.png)
[Title brushing] coco, who likes bananas

SQL考勤统计月报表

用Unity实现Flat Shading
随机推荐
【系统分析师之路】第五章 复盘软件工程(软件过程改进)
Knowledge dissemination cannot replace professional learning!
Yousi College: Six Sigma is not just statistics!
What is erdma as illustrated by Coptic cartoon?
[deep anatomy of C language] storage principle of float variable in memory & comparison between pointer variable and "zero value"
DeFi“钱从哪来”?一个大多数人都没搞清楚的问题
Details of gets, fgetc, fgets, Getc, getchar, putc, fputc, putchar, puts, fputs functions
香港回归20余年,图扑数字孪生港珠澳大桥,超震撼
MySQL access denied, opened as Administrator
[redis series] redis learning 16. Redis Dictionary (map) and its core coding structure
Wuenda 2022 machine learning special course evaluation is coming!
单元测试效率优化:为什么要对程序进行测试?测试有什么好处?
Optimization of unit test efficiency: why test programs? What are the benefits of testing?
Unity 频繁切换分支 结果模型出现莫名其妙的错误
Shell programming overview
重磅:国产IDE发布,由阿里研发,完全开源!
服务线上治理
exlipse同时操作多行。比如同时在多行同列输入相同的文字
华为帐号多端协同,打造美好互联生活
可观测,才可靠:云上自动化运维CloudOps系列沙龙 第一弹