了解互斥行为
Understanding mutex behviour
我在想 Go 中的 mutex
会锁定数据并且不允许任何其他 goroutine
read/write 除非拳头 goroutine
释放锁。看来我的理解是错误的。从其他 goroutine
中阻止 read/write 的唯一方法是在其他 goroutines
中也调用 lock
。这将确保 critical section
被一个且只有一个 goroutine
.
访问
所以,我预计 this 代码会出现死锁:
package main
import(
"fmt"
"sync"
)
type myMap struct {
m map[string]string
mutex sync.Mutex
}
func main() {
done := make(chan bool)
ch := make(chan bool)
myM := &myMap{
m: make(map[string]string),
}
go func() {
myM.mutex.Lock()
myM.m["x"] = "i"
fmt.Println("Locked. Won't release the Lock")
ch <- true
}()
go func() {
<- ch
fmt.Println("Trying to write to the myMap")
myM.m["a"] = "b"
fmt.Println(myM)
done <- true
}()
<- done
}
由于第一个 goroutine
锁定结构,我希望第二个 goroutine
无法 read/write 到结构,但这里没有发生。
如果我在第二个 goroutine
中添加 mux.Lock()
那么就会出现死锁。
我发现 mutex
在 Go 中的工作方式有点奇怪。如果我锁定,那么 Go 不应该允许任何其他 goroutine
到 read/write 到它。
谁能给我解释一下 Go 中的互斥量概念?
互斥体周围没有神奇的力场来保护它恰好嵌入其中的任何数据结构。如果锁定互斥体,它会阻止其他代码锁定它,直到它被解锁。仅此而已。 It's well documented in the sync
package.
所以在您的代码中,只有一个 myM.mutex.Lock()
,效果与没有互斥锁一样。
正确使用互斥锁来保护数据涉及在更新或读取数据之前锁定互斥锁,然后再将其解锁。通常这段代码会被包裹在一个函数中,这样就可以使用 defer 了:
func doSomething(myM *myMap) {
myM.mutex.Lock()
defer myM.mutex.Unlock()
... read or update myM
}
我在想 Go 中的 mutex
会锁定数据并且不允许任何其他 goroutine
read/write 除非拳头 goroutine
释放锁。看来我的理解是错误的。从其他 goroutine
中阻止 read/write 的唯一方法是在其他 goroutines
中也调用 lock
。这将确保 critical section
被一个且只有一个 goroutine
.
所以,我预计 this 代码会出现死锁:
package main
import(
"fmt"
"sync"
)
type myMap struct {
m map[string]string
mutex sync.Mutex
}
func main() {
done := make(chan bool)
ch := make(chan bool)
myM := &myMap{
m: make(map[string]string),
}
go func() {
myM.mutex.Lock()
myM.m["x"] = "i"
fmt.Println("Locked. Won't release the Lock")
ch <- true
}()
go func() {
<- ch
fmt.Println("Trying to write to the myMap")
myM.m["a"] = "b"
fmt.Println(myM)
done <- true
}()
<- done
}
由于第一个 goroutine
锁定结构,我希望第二个 goroutine
无法 read/write 到结构,但这里没有发生。
如果我在第二个 goroutine
中添加 mux.Lock()
那么就会出现死锁。
我发现 mutex
在 Go 中的工作方式有点奇怪。如果我锁定,那么 Go 不应该允许任何其他 goroutine
到 read/write 到它。
谁能给我解释一下 Go 中的互斥量概念?
互斥体周围没有神奇的力场来保护它恰好嵌入其中的任何数据结构。如果锁定互斥体,它会阻止其他代码锁定它,直到它被解锁。仅此而已。 It's well documented in the sync
package.
所以在您的代码中,只有一个 myM.mutex.Lock()
,效果与没有互斥锁一样。
正确使用互斥锁来保护数据涉及在更新或读取数据之前锁定互斥锁,然后再将其解锁。通常这段代码会被包裹在一个函数中,这样就可以使用 defer 了:
func doSomething(myM *myMap) {
myM.mutex.Lock()
defer myM.mutex.Unlock()
... read or update myM
}