为了从 Golang 的切片中删除元素,我应该把 `mutex` 放在哪里?父结构还是子结构?

问题描述 投票:0回答:1

假设我有 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
)中吗?

go struct synchronization slice mutex
1个回答
0
投票

由于端口切片是 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 同时修改。 关键是同步访问需要并发访问保护的共享数据结构。

© www.soinside.com 2019 - 2024. All rights reserved.