introduction
Locks in the program are one of the most powerful tools that many friends use when writing distributed applications.
Most of the students who use Go have experience in other languages, and they will have doubts about one of them, that isThe lock in Go does not support reentry?
To this end, today Fried Fish will take you to learn about the design considerations here and see why.
Reentrant lock
If you perform a "lock" operation on a normal mutex that has been locked, the result will either fail or block to unlock.
The lock scenario is as follows:
- On locking: If it is a reentrant mutex, if the thread currently trying to lock is the thread holding the lock, the locking operation will be successful.
- In unlocking: Reentrant mutex generally records the number of times it has been locked, and only if the same number of unlocking operations will be truly unlocked.
Simply put, reentrant mutex is a type of mutex lock. The same thread locks it multiple times and will not cause deadlocks or cause blockage.
Implementation may be more or less different from language, but the general meaning is similar.
Please think about it, what is Go like?
Go Support
We see the following example of Go mutex:
var mu func main() { () () }
Will this Go program block? No, the following error will be reported:
fatal error: all goroutines are asleep - deadlock!
Go obviously does not support reentrant mutex locks.
Official Reply
Go Design Principles
The fundamental reason for using mutual exclusion in projects is that in order to protect invariants, they can also be used to protect internal and external invariants.
Based on this, Go will abide by these principles in the design of mutex locks. as follows:
- In calling
When doing the method, it is necessary to ensure that the invariance of these variables remains and will not be destroyed in the subsequent process.
-
In calling
When doing the method, make sure:
- Programs no longer need to rely on those invariants.
- If the program breaks them during mutex locking, you need to make sure they have been restored.
Reasons for not supporting
After talking about Go's own design principles, why not support reentrability?
In fact, Russ Cox was in 2010 in "Experimenting with GO》 gave an answer, believing that recursion (also known as: reentry) mutual exclusion is a bad idea, and this design is not good.
We can understand it in combination with official examples.
as follows:
func F() { () ... do some stuff ... G() ... do some more stuff ... () } func G() { () ... do some stuff ... () }
In the above code, weF
Called in the methodMethod added a lock. If reentrant lock is supported, then it will enter
G
In the method.
There will be a fatal problem at this time, you don't knowF
andG
Did the method do something after locking it, which led to the destruction of the invariant? After all, it is entirely possible to start a few coroutines to do something bad.
This is unacceptable for Go, reentrant designViolating the design concept mentioned above, that is, "to ensure that the invariance of these variables remains and will not be destroyed in the subsequent process."
For the above reasons, the official Go team chose not to support this feature.
Summarize
Go mutex does not support the design of reentrant locks, and it is also my favorite idea of the simplest way. There are more possible interferences, so it is better to just do it simply.
The above is the detailed explanation of why Go does not support reentrant lock principle. For more information about Go's not supporting reentrant locks, please follow my other related articles!