假设我有 2 个结构如下:
type Device struct {
Ports []*TCPPort
}
type TCPPort struct {
ID int
State bool
Device *Device
}
创建
TCP-Port
时,会按如下方式附加:
// Body of the `createTCPPort is intentionally left blank. Imagine it creates a port and returns it.`
func createTCPPort() *TCPPort {}
tcp := createTCPPort()
device.Ports = append(device.Ports, tcp)
在任何给定时间,其中一个 TCP 端口都会请求删除。我想从这个片中删除/删除这个端口,我通过 device.Port
Ports []*TCPPort
附加端口。我现在猜测这个操作是否有序并不重要。我很困惑应该把 Mutex
放在哪里并使用它的功能,即 lock
和 unlock
。
我应该将它放在
Device
结构中吗?
type Device struct {
portMutex sync.Mutex
Ports []*TCPPort
}
// and then remove the element as follows:?
func (d Device) removePortFromSlice(){
d.portMutex.Lock()
defer d.portMutex.Lock()
// remove slice operation here
}
OR
type TCPPort struct {
PortMutex sync.Mutex
ID int
State bool
Device *Device
}
func (tcp TCPPort) removeElementFromSlice() {
tcp.portMutex.Lock()
defer tcp.portMutex.Lock()
// remove opearation here
}
我的问题是,我应该将互斥锁放入父结构(
Device
)还是子结构(TCPPort
)中吗?
由于端口切片是 Device 结构上的一个字段,因此将互斥锁放入 Device 中以同步对该特定字段的访问是有意义的。
以下是关于使用互斥锁的建议:
type Device struct {
portMutex sync.Mutex
Ports []*TCPPort
}
func (d *Device) RemovePort(port *TCPPort) {
d.portMutex.Lock()
defer d.portMutex.Unlock()
// Find index of port to remove
index := -1
for i, p := range d.Ports {
if p == port {
index = i
break
}
}
// Remove from slice
if index != -1 {
d.Ports = append(d.Ports[:index], d.Ports[index+1:]...)
}
}
这会在删除项目时锁定对 Ports 切片的访问。
将互斥量放在 TCPPort 上效果并不好,因为即使每个 TCPPort 结构都将被锁定,Device 中的切片仍然可以被其他 goroutine 同时修改。 关键是同步访问需要并发访问保护的共享数据结构。