Mutex.Lock()如何知道要锁定哪些变量?

时间:2019-06-22 21:39:14

标签: go concurrency multiprocessing mutex

我是新手,所以请保持温柔。

所以我已经在我的一些代码中使用互斥锁了几个星期了。我了解其背后的概念:锁定对特定资源的访问权限,与之交互(读或写),然后为其他人再次解锁。

我使用的互斥锁代码主要是复制粘贴调整。该代码可以运行,但是我仍在努力解决它的内部问题。到目前为止,我一直在结构中使用互斥锁来锁定该结构。今天,我发现了this example,这让我完全不清楚互斥锁实际上是在锁定什么。下面是一段示例代码:

var state = make(map[int]int)

var mutex = &sync.Mutex{}

var readOps uint64
var writeOps uint64

// Here we start 100 goroutines to execute repeated reads against the state, once per millisecond in each goroutine.
for r := 0; r < 100; r++ {
    go func() {
        total := 0
        for {
            key := rand.Intn(5)
            mutex.Lock()
            total += state[key]
            mutex.Unlock()
            atomic.AddUint64(&readOps, 1)

            time.Sleep(time.Millisecond)
        }
    }()
}

让我感到困惑的是,互斥锁和它应该锁定的值之间似乎没有任何联系。直到今天,我还认为互斥锁可以锁定特定的变量,但是看这段代码,似乎可以将整个程序锁定为仅执行锁定下方的行,直到再次运行解锁为止。我想这意味着所有其他goroutine都会暂停片刻,直到再次运行解锁。由于代码已编译,我想它可以知道在lock()unlock()之间访问了哪些变量,但是我不确定是否是这种情况。

如果所有其他程序都暂停片刻,这听起来并不像真正的多处理程序,那么我想我对所发生的事情没有很好的了解。

有人可以帮助我理解计算机如何知道应该锁定哪些变量吗?

1 个答案:

答案 0 :(得分:5)

  

锁定对特定资源的访问权限,与之交互(读或写),然后为其他人再次解锁。

基本上是。

  

让我感到困惑的是,互斥锁和应该锁定的值之间似乎没有任何联系。

Mutex只是一个互斥对象,它可以同步对资源的访问。这意味着,如果两个不同的goroutine要锁定互斥锁,则只有第一个可以访问它。现在,第二个goroutine会无限期等待,直到它本身可以锁定互斥体为止。与变量没有任何关系,您可以根据需要使用互斥体。例如,仅一个http请求,仅一个数据库读/写操作或仅一个变量分配。尽管我不建议在这些示例中使用互斥锁,但总体思路应该很清楚。

  

但是看这段代码,似乎可以以某种方式将整个程序锁定为仅执行锁下面的行,直到再次运行解锁为止。

不是整个程序,只有每个想要访问相同互斥锁的goroutine都等待直到可以。

  

我想这意味着所有其他goroutine都会暂停片刻,直到再次运行解锁。

不,他们不会暂停。他们执行直到想要访问相同的互斥锁为止。

如果您要使用变量将互斥锁专门分组,为什么不创建结构?