Happy life from the beginning of an article, although Go theme month has ended, I also wish to get my porcelain cup, but, I still want to continue to output the article, possibly this is ❤️
preface
Today, I want to talk about the concept of Mutex in Go. Literally, it is a concept of 🔒. In Go, Mutex is mainly used when goroutine concurrently operates on the same resource unit. Step by step, learn about Mutex in Go.
The body of the
We know that Mutex is in the SYNC package in Go, and its structure is very simple, which looks something like this
type Mutex struct {
state int32
sema uint32
}
Copy the code
Where, when state is set to 0, it is the unlocked state, and when state is set to 1, it is the locked state.
The other parameter is a semaphore, which is used to queue up after a failed lock (more on that later).
Lock grab mode
Go can be divided into two modes of snatch lock, one is normal mode, the other is hunger mode
Normal mode
At the beginning, it is in normal mode, that is, when G1 holds a lock, G2 spins to try to acquire it
When the lock is not acquired after 4 spins, G2 is added to the lock queue, and the order of G in the queue is determined by the semaphore.
At this point, if G1 releases the lock, AT this point, G2 is awakened from the queue to compete for the lock, and not only is there a G2 competing for the lock, but there are other spinning G’s competing for the lock as well.
At this point, because G2 is awakened to grab the lock, it is less likely to acquire the lock than G4 and G5, which are already spinning in the CPU. If it fails to acquire the lock, G2 will be rejoined to the head of the queue to continue the next round of waiting.
But obviously, that’s not going to work, because it’s going to cause G in the queue to go unexecuted for a long time, so you have starvation mode.
Starvation mode
When in the waiting queue Goroutine more than 1 ms do not have access to lock, its state will turn into a starvation mode, this time, if the G1 lock to release, G2 can direct access to the lock, rather than through contest, at the same time, the subsequent G4 and G5 will not enter the spin state, They went straight to the back of the queue
Therefore, it is impossible to keep a state of hunger forever. There will always be a time when Mutex is full, that is, there will always be a moment when Mutex will return to the normal mode. The conditions for returning to the normal mode are as follows
1. The execution time of G2 is less than 1ms
2. The waiting queue has been cleared
When either of the above two conditions is met, Mutex will switch back to the normal mode, and Go’s lock snatching process switches back and forth between the normal mode and starvation mode.
In normal mode, the application makes the Goroutine spin state, because to avoid the high cost of waking and sleeping the Goroutine, it increases the throughput by using the spin + queue mode, but this way, it is easy to have a tail delay.
In starvation mode, goroutines are queued and executed in strict order, so there is no tail lag, but the program throughput is not as high as in normal mode.
The spin of Goroutine
In normal mode, a new Goroutine will enter a spin state to capture the lock. Therefore, any new Goroutine will enter a spin state. In order to enter a spin state, the following conditions must be met.
-
It has to be a multi-core machine
-
Gomaxproces must be greater than 1
-
In addition to the running P, there must be other P’s in the running state
-
The current local queue for run P is empty
Only when all four conditions are met will the Goroutine enter a spin state.
The last
Recently in see Go about lock some source code, there are some small video, here to make some summary, if you think this article is helpful to you, click a like and then Go!!