了解互斥体行为

she*_*eer -1 multithreading mutex go goroutine

我在想mutex在 Go 中会锁定数据并且不允许任何其他人读/写,goroutine除非拳头goroutine释放锁。看来我的理解是错误的。阻止其他人读/写的唯一方法goroutine是调用lock其他goroutines人。这将确保critical section只有一个访问goroutine

所以,我希望这段代码有一个死锁:

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
}

Run Code Online (Sandbox Code Playgroud)

由于拳头goroutine锁定了结构,我希望第二个goroutine无法读取/写入结构,但这里不会发生这种情况。

如果我添加mux.Lock()第二个,goroutine那么就会出现僵局。

我觉得mutexGo 的工作方式有点奇怪。如果我锁定,那么 Go 不应该允许任何其他goroutine人读/写它。

有人可以向我解释 Go 中的互斥量概念吗?

Pau*_*kin 5

互斥锁周围没有神奇的力场,保护它恰好嵌入其中的任何数据结构。如果锁定互斥锁,它会阻止其他代码锁定它,直到它被解锁。不多也不少。它在sync包中有详细记录。

因此,在您的代码中,正好有一个myM.mutex.Lock(),效果与没有互斥锁一样。

保护数据的互斥锁的正确使用包括在更新或读取数据之前锁定互斥锁,然后再将其解锁。这段代码通常会被封装在一个函数中,以便可以使用 defer:

func doSomething(myM *myMap) {
    myM.mutex.Lock()
    defer myM.mutex.Unlock()
    ... read or update myM
}
Run Code Online (Sandbox Code Playgroud)