【发布时间】:2026-01-29 01:50:01
【问题描述】:
我有一个结构如下。
type User struct {
Mutex sync.RWMutex
Username string
Stuff map[string]string
}
我也有以下全局。
var MyUsers []User
var UserMutex sync.RWMutex
由于我的应用程序每秒访问MyUsers 切片数千次,我认为这将是管理性能的最佳方式。如果我想修改一个单独的 MyUsers 元素,那么我将锁定该特定元素:
MyUsers[x].Mutex.Lock()
然后进行任何修改并解锁它。
我的问题是,这样做安全吗?我有普通的全局UserMutex 仅在附加到切片时锁定切片......但是当附加到切片时,所有现有元素是否都在内存中移动?
如果一个线程同时附加到切片,而另一个线程正在修改一个元素,会发生什么?这可以在上面的设置中发生吗?
我是否可以使用make() 分配足够大的切片,以便任何append() 都不会影响内存中的位置?
【问题讨论】:
-
永远,从字面上永远永远不会将 sync.WhateverMutex 设置为结构的字段。始终使用 *sync.WahteverMutex,因为您必须 不复制sync.Mutex。并且在追加到切片期间可能会复制元素。另外:您必须在追加时防止 所有 修改,因此个人保护必须包括对 MyUsers 的读取锁定。也许你应该重新设计,但很难说。
-
@Volker:互斥量值非常常见和惯用,无论是嵌入的还是作为命名字段。此外,
go vet警告如果您不使用指向结构的指针,则复制互斥锁值。我认为整个 std 库中实际上没有一个*sync.Mutex字段。 -
@JimB 是的,如果包含 Mutex 的结构总是通过指针传递,那很好。 OP 的
var MyUsers []User和var MyUsers []User不属于此类别。我承认这个建议太强烈了。 -
@Volker: 是的,
[]User类型是这里的问题,尽管在复制互斥体时完全编写 any 测试会失败,所以我希望有一个永远不会走得太远。