作为golang的初学者,我发现golang的互斥 不是re-entranceLock 来自书籍The Go Programming Language
。他们解释原因:
似乎解释很详细,不幸的是我无法得到它。我还不知道什么时候应该使用不能重新入口,如果没有,我会收到什么不好的惊喜?如果有人能给我一个例子,我将不胜感激。Go的互斥体不可重入是有充分理由的。互斥锁的目的是确保在程序执行期间在关键点维护共享变量的某些不变量。其中一个不变量是"没有goroutine访问共享变量,"但是可能存在特定于互斥锁保护的数据结构的其他不变量。当goroutine获取互斥锁时,它可能会认为不变量成立。虽然它持有 锁定,它可能会更新共享变量,以便暂时违反不变量。 但是,当它释放锁时,它必须保证订单已经恢复并且不变量再次保持。虽然可重入的互斥锁可以确保没有其他goroutine访问共享变量,但它无法保护这些变量的其他不变量。
答案 0 :(得分:0)
以下是糟糕代码的示例,仅用于说明问题:
package main
import (
"fmt"
"sync"
)
type SafeCounter struct {
lock sync.Mutex
count int
enabled bool
NextValue func(int) int
}
const maxCount = 10
func (c *SafeCounter) Count() int {
return c.count
}
func (c *SafeCounter) Increment() {
c.lock.Lock()
if c.enabled {
c.count = c.NextValue(c.count)
}
c.lock.Unlock()
}
func (c *SafeCounter) SetEnabled(enabled bool) {
c.lock.Lock()
c.enabled = enabled
if !enabled {
c.count = 0
}
c.lock.Unlock()
}
func main() {
var counter SafeCounter
counter.SetEnabled(true)
counter.NextValue = func(value int) int {
if counter.Count() > maxCount {
// Safe counter doesn't expect this here!
// The program will panic in SetEnabled
counter.SetEnabled(false)
}
return value + 1
}
for i := 0; i < 100; i++ {
doAction()
counter.Increment()
}
fmt.Println(counter.Count())
}
func doAction() {
// some action
}
Increment
和SetEnabled
都获得锁定,因为他们不能允许enabled
和count
的值在他们位于中间时发生变化东西。但是,如果锁是重入(递归),那么它将被允许(因为两个调用都在相同的goroutine上运行)。