gpt4 book ai didi

dictionary - 我应该在范围之前锁定 map 吗?

转载 作者:IT王子 更新时间:2023-10-29 02:23:11 25 4
gpt4 key购买 nike

如果多个 goroutine 将运行 notifyAll func,那么在不锁定的情况下进行范围映射是否安全?实际上在一个范围内,我有时需要从 map 中删除条目。

var mu sync.RWMutex

func (self *Server) notifyAll(event *Event)
ch := make(chan int, 64)
num := 0
for k, v := range self.connections {
num++
ch <- num

go func(int k, conn *Conn) {
err := conn.sendMessage(event)
<-ch
if err != nil {
self.removeConn(k)
}
}(k, v)
}
}

func (self *Server) removeConn(int k) {
mu.Lock()
defer mu.Unlock()
delete(self.connections, k)
}

// Somewhere in another goroutine
func (self *Server) addConn(conn *Conn, int k) {
mu.Lock()
defer mu.Unlock()
self.connections[k] = conn
}

或者我必须在范围之前锁定 map ?

func (self *Server) notifyAll(event *Event)
mu.RLock()
defer mu.RUnlock()
// Skipped previous body...
}

最佳答案

简短的回答: map 在 Go 中不是并发安全的(仍然可以说是线程安全的)。

因此,如果您需要从不同的 go-routines 访问 map ,您必须采用某种形式的访问编排,否则“不受控制的 map 访问可能会使程序崩溃”(参见 this)。

编辑:

这是另一种实现(不考虑管家问题——超时、退出、日志等),它完全忽略互斥锁并使用更 Goish 的方法(这只是为了演示这种方法,它可以帮助我们清除访问编排问题- 可能适合或不适合您的情况):

type Server struct {
connections map[*Conn]struct{}

_removeConn, _addConn chan *Conn
_notifyAll chan *Event
}

func NewServer() *Server {
s := new(Server)
s.connections = make(map[*Conn]struct{})
s._addConn = make(chan *Conn)
s._removeConn = make(chan *Conn, 1)
s._notifyAll = make(chan *Event)
go s.agent()
return s
}

func (s *Server) agent() {
for {
select {
case c := <-s._addConn:
s.connections[c] = struct{}{}
case c := <-s._removeConn:
delete(s.connections, c)
case e := <-s._notifyAll:
for c := range s.connections {
closure := c
go func() {
err := closure.sendMessage(e)
if err != nil {
s._removeConn <- closure
}
}()
}
}
}
}

func (s *Server) removeConn(c *Conn) {
s._removeConn <- c
}

func (s *Server) addConn(c *Conn) {
s._addConn <- c
}

编辑:

我是正确的;根据 Damian Gryski映射对于并发读取是安全的。 map 顺序在每次迭代中发生变化的原因是“为 map 迭代顺序选择的随机种子,对于 goroutine 迭代是本地的”(他的另一个 tweet)。这个事实不会影响第一次编辑和建议的解决方案。

关于dictionary - 我应该在范围之前锁定 map 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37404025/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com