【发布时间】:2021-09-12 00:20:36
【问题描述】:
阅读 golang.org 和 stackoverflow 上的互斥锁示例后,我仍然不确定匿名函数的声明和惯用用法。所以我总结了几个例子。
示例 A、B 和 C 是否几乎相同,或者是否存在我没有注意到的主要差异? 我更喜欢全局示例“B”。我想如果我小心一点,这可能是最简单的解决方案。
或者有没有更好的方法来使用互斥锁?
package main
import (
"fmt"
"sync"
)
type MuContainer struct {
sync.RWMutex
data int
}
var mucglobal = &MuContainer{}
func main() {
// A: Global declaration - working: adds 45
for i := 0; i < 10; i++ {
go func(j int, mucf *MuContainer) {
mucf.Lock()
mucf.data += j
mucf.Unlock()
}(i, mucglobal)
}
// B: Global only - working: adds 45
for i := 0; i < 10; i++ {
go func(j int) {
mucglobal.Lock()
mucglobal.data += j
mucglobal.Unlock()
}(i)
}
// C: Local declaration - working: adds 45
muclocal := &MuContainer{}
for i := 0; i < 10; i++ {
go func(j int, mucf *MuContainer) {
mucf.Lock()
mucf.data += j
mucf.Unlock()
}(i, muclocal)
}
// // D: Pointer to struct - not working: adds 0
// // I guess because it points directly to the struct.
// for i := 0; i < 10; i++ {
// go func(j int, mucf *MuContainer) {
// mucf.Lock()
// mucf.data += j
// mucf.Unlock()
// }(i, &MuContainer{})
// }
for {
mucglobal.RLock()
muclocal.RLock()
fmt.Printf("global: %d / local: %d\n", mucglobal.data, muclocal.data)
if mucglobal.data == 90 && muclocal.data == 45 {
muclocal.RUnlock()
mucglobal.RUnlock()
break
}
muclocal.RUnlock()
mucglobal.RUnlock()
}
}
【问题讨论】:
-
查看相关/可能的重复:When do you embed mutex in struct in Go?
-
A、B 和 C 之间没有实质性区别。您可能在这里高估了“惯用语”。
-
A 和 B 是相同的。 C 在现实世界的代码中可能会或可能不会以不同的方式工作(取决于是否有其他代码访问相同的包 var),但在此代码中,它与 A 和 B 相同。D 在这种情况下没有任何意义,可能或可能在任何其他假设情况下无效。
-
你混淆了不同的东西。互斥锁是互斥锁。通常,您使用 *sync.Mutex,而不是互斥锁,因为不得复制互斥锁。嵌入互斥体是可以的,但如果您对互斥体、结构字面量和 popinters 感到不舒服:为什么不使用简单的(未嵌入的)字段。你可能想多了。
-
免责声明:我不知道您的代码要做什么或要解决哪个问题。有时全局或局部变量都可以,然后有一个块
var ( xyzMu = new(sync.Mutex); xyz XYZ)就可以了。互斥锁和受该互斥锁保护的变量并排放置。有时最好将互斥锁作为一个字段。如果您使用一个字段,您可以拥有一个“普通”字段或“嵌入”一个互斥锁(您的代码嵌入它)。对于该语言的新手来说,经验嵌入是有问题的。如果你做到正确,那么如何做到这一点并不重要。