Go concurrent programming learning-class1

class1. Mutex solves concurrent resource access

Insert image description here

basic concepts

Critical section concept: a shared resource that can be accessed concurrently. Through the Mutex mutex, the critical section can be restricted to be acquired by only one thread.

  1. According to different situations, different applicable scenarios

●Shared resources. Concurrent reading and writing of shared resources will cause data race problems, so concurrency primitives such as Mutex and RWMutex are needed to protect them. ●Task arrangement. Goroutines need to be executed according to certain rules, and there is a sequential relationship between goroutines that wait for or depend on each other. We often use WaitGroup or Channel to achieve this. ●Message passing. Information exchange and thread-safe data exchange between different goroutines are often implemented using Channel.




  1. Both Mutex and RWMutex implement the lock interface in sync.
3. type Locker interface{
    
    
4. 	Lock()
5. 	Unlock()
6. }

Spin lock: means that when a thread acquires the lock, if the lock has been acquired by other threads, then the thread will wait in a loop, and then continuously determine whether the lock can be It is enough to be successfully acquired, and the loop will not exit until the lock is obtained. The thread that acquires the lock continues to be active, does not hang (not blocks the process through sleep), and continues to occupy the CPU

Normal mode: All goroutines acquire locks in FIFO order. The awakened goroutine and the goroutine that newly request the lock acquire the lock at the same time. It is usually easier for the goroutine that newly requests the lock. Acquire the lock (continue to occupy the CPU), it is not easy for the awakened goroutine to acquire the lock

Hungry mode: All goroutines trying to acquire locks are queued. Goroutines that newly request locks will not acquire locks (spin is disabled), but will join the end of the queue and wait for acquisition. lock

Concurrency problem testing tool

When compiling, testing or running Go code, if you add the race parameter, you may find concurrency problems. We can add the race parameter to run and check whether there are any concurrency problems. If you go run -race counter.go, a warning message will be output.
For example: go run -race main.go
Lock before the critical resource and release the lock when leaving the critical section

There is one thing to note here: the zero value of Mutex is an unlocked state where no goroutine is waiting, so you do not need additional initialization, just declare the variable directly (such as var mu sync.Mutex).

If the embedded struct has multiple fields, we usually put the Mutex on the field to be controlled, and then use spaces to separate the fields. Even if you don't do this, the code will compile normally, but if written in this style, the logic will be clearer and easier to maintain. You can even encapsulate the logic of acquiring locks, releasing locks, and counting incremented by one into a method, without exposing logic such as
to the outside world:

Thinking questions

如果 Mutex 已经被一个 goroutine 获取了锁,其它等待中的 goroutine 们只能一直等待。那么等这个锁释放后,等待中的goroutine 中哪一个会优先获取 Mutex 呢?

Answer:
The waiting goroutines are queued in FIFO
1) When Mutex is in normal mode, if there are no new goroutines and If the team leader goroutine competes, the team leader goroutine will get it. If there is competition for new goroutines, there is a high probability that new goroutines will be obtained.
2) When the queue head goroutine fails to compete for the lock 1ms later, it will adjust the Mutex to starvation mode. After entering starvation mode, the ownership of the lock will be transferred directly from the unlocking goroutine to the head goroutine. At this time, the new goroutine will be directly placed at the end of the team.
3) When a goroutine acquires the lock, if it finds that it meets any of the following conditions
1. It is the last one in the queue < a i=6> 2. If it waits for the lock for less than 1ms, it switches the lock back to normal mode

The reason why a goroutine that newly requests a lock is easier to acquire a lock:
In official terms, a goroutine that newly requests a lock has an advantage. It is executing on the CPU, and there may be several , so the Goroutine that has just been awakened is very likely to fail in the lock competition.

For more information, please refer to the boss’s article::Go Mutex Hungry Mode:
Another boss’s summary:Go_Concurrency learning address
Learn from: Geek Time’s new column "Go Concurrency Programming Practical Course"

Guess you like

Origin blog.csdn.net/weixin_54174102/article/details/134499802