multithreading - 了解互斥行为

标签 multithreading go mutex goroutine

我当时在想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中的互斥量概念吗?

最佳答案

互斥锁周围没有神奇的力场,可以保护它恰好嵌入其中的任何数据结构。如果锁定了互斥锁,它将阻止其他代码对其进行锁定直到被解锁。仅此而已。 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
}

关于multithreading - 了解互斥行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63434403/

相关文章:

c - P线程同步: Back & Forth Reading of Two Text Files

c - 让我确保我理解 C pthread 互斥体

java - 这是 Android 线程的安全使用吗?

java - 这个线程程序每次都会向我显示不同的答案

c++ - 无法关闭 QThread - 应用程序崩溃

json - Golang 将字符串转换为单独的 json 值而不是列表,类似于 python 中的 json.loads

go - 将缓冲区绘制到屏幕时绑定(bind)不匹配 (golang.org/x/exp/shiny/screen)

java - 如何使用Java多线程检索mysql数据

json - 将嵌套 JSON 响应解码为嵌套结构

go - 最大限度地减少 map 上的锁定 - 而是尽快锁定单个项目