我应该把`mutex`放在哪里,以便从Go中的切片中删除一个元素?父结构还是子结构?

brccelvz  于 2023-08-01  发布在  Go
关注(0)|答案(2)|浏览(79)

假设我有两个结构体如下:

type Device struct {
     Ports []*TCPPort
}

type TCPPort struct {
     ID int
     State bool
     Device *Device
}

字符串
当创建TCPPort时,它被追加如下:

// 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端口。我想从我通过设备附加端口的切片中删除/移除此端口。端口Ports []*TCPPort。我想目前这个行动是否有序并不重要。我很困惑,我应该把Mutex放在哪里,并使用它的功能,这是lockunlock
我应该像下面这样把它放在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
}

  • 或者 *
type TCPPort struct {
     PortMutex sync.Mutex
     ID int
     State bool
     Device *Device
}

func (tcp TCPPort) removeElementFromSlice() {
    tcp.portMutex.Lock()
    defer tcp.portMutex.Lock()
    // Remove operation here
}


我应该把互斥体放在父结构体Device还是子结构体TCPPort中?

tag5nh1u

tag5nh1u1#

由于端口片是Device结构体上的一个字段,因此将互斥锁放在Device中以同步对该特定字段的访问是有意义的。
下面是关于使用mutex的建议:

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

vhipe2zx

vhipe2zx2#

是的,您可以使用Mutex安全地处理对Device结构中Ports切片的并发访问。将Mutex放在Device结构体中是一种合理的方法。
以下是如何修改Device结构并添加方法,以使用Mutex安全地添加和删除TCP端口:

import "sync"

type Device struct {
    Ports []*TCPPort
    mu    sync.Mutex // Mutex to protect access to Ports
}

type TCPPort struct {
    ID     int
    State  bool
    Device *Device
}

// Method to add a TCP port to the Device's Ports slice safely
func (d *Device) AddPort(tcp *TCPPort) {
    d.mu.Lock()
    defer d.mu.Unlock()
    d.Ports = append(d.Ports, tcp)
}

// Method to remove a TCP port from the Device's Ports slice safely
func (d *Device) RemovePort(tcp *TCPPort) {
    d.mu.Lock()
    defer d.mu.Unlock()

    // Find the index of the TCP port in the Ports slice
    var index int
    for i, port := range d.Ports {
        if port == tcp {
            index = i
            break
        }
    }

    // Remove the TCP port from the slice
    d.Ports = append(d.Ports[:index], d.Ports[index+1:]...)
}

字符串
现在,当您想要添加或删除TCP端口时,可以分别使用Device结构体的AddPort和RemovePort方法来完成。Mutex确保一次只有一个goroutine可以修改Ports切片,从而提供并发安全性。

相关问题