了解互斥行为

我本以为Go中的mutex会锁定数据,并且不允许其他任何goroutine进行读/写,除非拳头goroutine释放了锁定。看来我的理解是错误的。阻止从其他goroutine读取/写入的唯一方法是也调用其他lock中的goroutines。这样可以确保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无法对该结构进行读/写操作,但这在这里不会发生。

如果我要在第二mux.Lock()中添加goroutine,则会出现死锁。

我发现mutex在Go中的工作方式有点怪异。如果我锁定了,那么Go不应允许其他任何goroutine对其进行读写。

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

iCMS 回答:了解互斥行为

互斥体周围没有神奇的力场,可以保护它恰好嵌入其中的任何数据结构。如果锁定了互斥体,它将防止其他代码锁定它直到解锁。仅此而已。 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
}
本文链接:https://www.f2er.com/1737783.html

大家都在问