首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >sync.Mutex和*sync.Mutex哪个更好?

sync.Mutex和*sync.Mutex哪个更好?
EN

Stack Overflow用户
提问于 2018-04-13 02:56:56
回答 3查看 10K关注 0票数 15

在Go中,我们可以使用:

代码语言:javascript
运行
复制
type Data struct {
    lock  *sync.Mutex
}

代码语言:javascript
运行
复制
type Data struct {
    lock  sync.Mutex
}

然后,像这样使用:

代码语言:javascript
运行
复制
func (d *Data) Update() {
   d.lock.Lock()
   defer d.lock.Unlock()
   // update
}

我能想到的不同之处是,*sync.Mutex只需要实例化即可使用。

sync.Mutex*sync.Mutex在Go中有什么区别,哪一个更好?

EN

回答 3

Stack Overflow用户

发布于 2020-01-29 10:38:25

mkopriva的评论是正确的,应该是公认的答案。

然而,在阅读OP的问题时,我认为可能有一个潜在的误解值得扩展:OP提到唯一的区别是“一个必须初始化,另一个不需要初始化”。

指向TT的指针之前的基本区别意味着在使用变量时一系列的行为更改,其中只有一个是它的实例化。

首先,在这两种情况下都存在实例化。在T情况下,它隐含在声明中,因为变量包含实例本身(可以这么说)。但是在指针的情况下,它可能发生在代码中完全不同的位置,因为变量只包含对实例的间接。这解释了为什么只有指针变量才能导致“零指针取消引用”:只有在这种情况下,您的代码才能尝试在变量实际初始化之前对其执行任何操作。

其次:使用一个具体的T,加上go是一个“通过价值”的语言,意味着每个调用都复制任何具体的函数参数(或方法接收者)。

这至少在三个方面产生了影响:

  • 性能:如果被复制的实例是大的struct\s,并且调用发生在应用程序的热路径中,那么您将复制大量的数据。
  • 内存使用情况:与上面所述类似:如果您有长时间运行的goroutines接收大量的struct\s,这些副本可能会对应用程序的内存占用产生影响。
  • 语义:这可以说是最重要的区别:如果您的类型有应该修改其内容的方法,那么您几乎可以使用来使用指针接收器。否则,该方法将对副本进行操作,并且更改将是不可见的。其必然结果也同样重要:如果您希望向您的方法发出不会修改其接收器的信号,那么使用具体类型(可能包含未导出的内容)是实现这一目标的好方法。

最后,这就引出了sync.Mutex的具体案例:查看上面的要点和代码,我们可以看到性能和内存的使用通常不是一个问题,因为struct

然而,最后一点非常重要:拥有指向sync.Mutex的指针意味着什么?这意味着包含struct的副本将指向同一个锁。也就是说,struct的两个实例可能共享一个锁。

由于go vet不会抱怨将指针复制到互斥对象,所以复制父struct不会引起警报,您可能最终会用相同的锁保护两个单独的实例,这可能会导致死锁。

总之:除非知道,否则您想要保护具有相同锁的东西的不同副本(IMHO有点不太可能),最好使用具体的sync.Mutex\es。

如果创建sync.Mutex指针的唯一原因是因为go vet告诉您不要复制它,那么您可能应该考虑在试图保护的struct上查找一层:很可能是通过一个具体的接收器(如

代码语言:javascript
运行
复制
func (t T) foo(){...}

你应该去的地方

代码语言:javascript
运行
复制
func (t *T) foo(){...}
票数 11
EN

Stack Overflow用户

发布于 2018-04-13 05:27:43

  • 我认为您可以将*sync.Mutex看作一个简单的指针。如果您想使用它,您应该声明和插入它,但是如果您使用sync.Mutex,它已经被输入了。
  • 顺便说一下,在k8s源代码中,它们总是传递变量指针以供使用,因为传递结构将执行副本,但如果使用指针,则只需传递一个指针。(我的意思是你不需要复印)。
票数 4
EN

Stack Overflow用户

发布于 2021-07-30 22:11:20

它们并不完全相同:

  • sync.Mutex:在这里,您可以立即使用Unlock的函数Lock
  • *sync.Mutex:这里您必须在使用函数之前初始化,比如如果您想要从其他对象复制实例,因为如果您尝试使用上述方式(没有指针)从其他对象复制,它将向您展示警告assignment copies lock value to xxxxxx: sync.Mutex copylocks女巫,您可以在这个答案中找到它的解决方案。
  • 但是这两种类型都接受您使用函数LockUnlock,因为函数被声明为指针接收器,并且这种声明函数的方式接受直接在对象或指针上使用,就像您所拥有的一样。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49808622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档