在Golang,我们可以使用:
type Data struct {
lock *sync.Mutex
}
或
type Data struct {
lock sync.Mutex
}
并且,使用这样:
func (d *Data) Update() {
d.lock.Lock()
defer d.lock.Unlock()
// update
}
我能想到的区别是*sync.Mutex
需要实例化才能使用。
Golang中sync.Mutex
和*sync.Mutex
之间有什么区别?哪个更好?
答案 0 :(得分:1)
答案 1 :(得分:1)
comment from mkopriva是正确的,应该是可以接受的答案。
但是,在阅读OP的问题时,我认为可能存在一个值得进一步扩大的潜在误解:OP提到唯一的区别是“一个必须初始化,另一个不必初始化”。
指向T
和T
的指针之前的根本区别意味着使用变量时会发生一系列行为更改,其中只有一个是其实例化。
首先:两种情况下都存在实际的实例。在T
情况下,它隐含在声明中,因为变量包含实例本身(可以这么说)。但是在指针的情况下,它可能发生在代码中完全不同的位置,因为变量仅包含实例的间接寻址。这解释了为什么只有指针变量会导致“无指针取消引用”的原因:只有在这种情况下,您的代码才能在变量真正初始化之前尝试对它执行任何操作。
第二:使用具体的T
以及go是"pass by value" language这一事实,意味着每次调用都会复制任何具体的函数参数(或方法接收者)。
这至少在三个方面产生了影响:
struct
| s,并且调用发生在应用程序的热路径中,那么您将在周围复制大量数据。struct
|,那么这些副本可能会影响应用程序的内存占用。最后,这将我们引到sync.Mutex
的具体情况:通过以上几点和代码,我们可以看到性能和内存使用率通常不是问题,因为sync.Mutex
is a pretty small struct
。 br />
但是,最后一点 非常重要:指向sync.Mutex
的指针 是什么意思?这意味着包含struct
的副本将指向相同的锁。即:这意味着您的struct
的两个实例可能会共享一个锁。
由于go vet
不会抱怨将 pointers 复制到互斥锁,因此复制父struct
不会引起警告,您可能最终会保护两个具有相同锁的单独实例,这可能导致僵局。
总之:除非您知道,否则要保护具有相同锁的东西的不同副本(恕我直言不太可能),否则最好使用具体的sync.Mutex
| es。< br />
如果制作sync.Mutex
指针的唯一原因是因为go vet
告诉您不要复制它,那么您可能应该考虑在您要保护的struct
上向上看一层:可能是由于使用
func (t T) foo(){...}
您应该在的地方
func (t *T) foo(){...}
答案 2 :(得分:0)
它们并不完全相同:
sync.Mutex:在这里你可以直接使用Lock
的{{1}}函数。
*sync.Mutex:这里你必须在使用函数之前进行初始化,就像你想从其他对象复制实例一样,因为如果你尝试使用上面的方式(没有指针)从其他对象复制它会向您显示警告 Unlock
,您可以在 this answer 中找到它的解决方案。
但是这两种类型都接受您使用函数 assignment copies lock value to xxxxxx: sync.Mutex copylocks
或 Lock
因为函数被声明为 Pointer receivers 并且这种声明函数的方式接受直接使用在一个对象或一个指针上,比如你所拥有的