互斥锁 – 全局还是局部,以及惯用法的使用?

huangapple go评论77阅读模式
英文:

Mutex - global or local and idiomatic usage?

问题

在阅读了golang.org和stackoverflow上的互斥锁示例之后,我仍然不确定关于匿名函数的声明和惯用用法。因此,我总结了一些示例。

A、B和C这几个示例是否几乎等效,还是有我没有注意到的重大差异?
我更喜欢全局示例"B"。我猜如果我小心使用它,它可能是最简单的解决方案。

或者也许有更好的使用互斥锁的方法吗?

这个在go playground上的示例

package main

import (
	"fmt"
	"sync"
)

type MuContainer struct {
	sync.RWMutex
	data int
}

var mucglobal = &MuContainer{}

func main() {

	// A: 全局声明 - 工作正常:添加45
	for i := 0; i < 10; i++ {
		go func(j int, mucf *MuContainer) {
			mucf.Lock()
			mucf.data += j
			mucf.Unlock()
		}(i, mucglobal)
	}

	// B: 仅全局 - 工作正常:添加45
	for i := 0; i < 10; i++ {
		go func(j int) {
			mucglobal.Lock()
			mucglobal.data += j
			mucglobal.Unlock()
		}(i)
	}

	// C: 局部声明 - 工作正常:添加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: 指向结构体的指针 - 不工作:添加0
	// // 我猜是因为它直接指向了结构体。
	// 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()
	}
}
英文:

After reading the mutex examples on golang.org and stackoverflow, I'm still not sure about the declaration and idiomatic usage with anonymous functions. Therefore I've summarized a few examples.

Are examples A, B and C nearly equivalent or are there major differences that I don't notice?
I would prefer the global example "B". I guess if I'm careful with it, it's probably the simplest solution.

Or is there maybe a better approach to use mutex?

This example on go playground

package main
import (
&quot;fmt&quot;
&quot;sync&quot;
)
type MuContainer struct {
sync.RWMutex
data int
}
var mucglobal = &amp;MuContainer{}
func main() {
// A: Global declaration - working: adds 45
for i := 0; i &lt; 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 &lt; 10; i++ {
go func(j int) {
mucglobal.Lock()
mucglobal.data += j
mucglobal.Unlock()
}(i)
}
// C: Local declaration - working: adds 45
muclocal := &amp;MuContainer{}
for i := 0; i &lt; 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 &lt; 10; i++ {
// 	go func(j int, mucf *MuContainer) {
// 		mucf.Lock()
// 		mucf.data += j
// 		mucf.Unlock()
// 	}(i, &amp;MuContainer{})
// }
for {
mucglobal.RLock()
muclocal.RLock()
fmt.Printf(&quot;global: %d / local: %d\n&quot;, mucglobal.data, muclocal.data)
if mucglobal.data == 90 &amp;&amp; muclocal.data == 45 {
muclocal.RUnlock()
mucglobal.RUnlock()
break
}
muclocal.RUnlock()
mucglobal.RUnlock()
}
}

答案1

得分: 3

D不起作用是因为你在每次迭代中创建了一个新的结构体。最终,你将拥有10个独立的MuContainer实例。

前两个选项在语义上是相同的。对于这两个选项来说,每个goroutine共享同一个对象实例,该实例恰好是一个全局变量。

第二个选项与第一个选项类似,唯一的区别是被锁定和更新的对象恰好是一个局部变量。同样,这些goroutine都在同一个对象实例上工作。

因此,它们实际上并没有太大的区别,而且这三个选项都有各自的用途。

英文:

D is not working because you are creating a new struct for each iteration. In the end, you'll have 10 independent instances of MuContainer.

The first two options are semantically identical. The bottom line for those two is that each goroutine shares the same instance of the object, which happens to be a global var.

The second one is similar with the only difference being the object locked and updated happens to be a local var. Again, the goroutines are working on the same instance of the object.

So these are not really different from each other, and all three have their uses.

huangapple
  • 本文由 发表于 2021年6月30日 03:32:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/68184633.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定