我有这两个功能:
// PartyHub struct contains all data for the party
type PartyHub struct {
FullPartys map[string]Party
PartialPartys map[string]Party
Enter chan Member
Leave chan Member
sync.Mutex
}
// RemoveFromQueue will remove the member from party
func (p *PartyHub) RemoveFromQueue(memberLeaving Member, inQueue bool) {
if !inQueue {
return
}
for _, party := range p.PartialPartys {
go func(party Party) {
if _, ok := party.Members[memberLeaving.Identifier]; ok {
p.Lock()
->>>>>>>> delete(party.Members, memberLeaving.Identifier)
p.Unlock()
}
}(party)
}
log.Println("Removing")
}
// SortIntoParty will sort the member into party
func (p *PartyHub) SortIntoParty(newMember Member, inQueue bool) {
log.Println(inQueue)
if inQueue {
return
}
log.Println("Adding")
foundParty := false
->> for partyid, party := range p.PartialPartys {
if !party.Accepting {
continue
}
goodFitForParty := true
for _, partyMember := range party.Members {
if newMember.Type == partyMember.Type && newMember.Rank >= partyMember.Rank-partyMember.RankTol && newMember.Rank <= partyMember.Rank+partyMember.RankTol {
goodFitForParty = true
continue
} else {
goodFitForParty = false
break
}
}
if !goodFitForParty {
continue
} else {
foundParty = true
newMember.Conn.CurrentParty = partyid
p.Lock()
p.PartialPartys[partyid].Members[newMember.Conn.Identifier] = newMember
p.Unlock()
if len(party.Members) == 2 {
p.Lock()
party.Accepting = false
p.Unlock()
// Start Go Routine
}
break
}
}
if !foundParty {
uuid := feeds.NewUUID().String()
newMember.Conn.CurrentParty = uuid
p.Lock()
p.PartialPartys[uuid] = Party{Accepting: true, Members: make(map[string]Member), Ready: make(chan *Connection), Decline: make(chan *Connection)}
p.PartialPartys[uuid].Members[newMember.Conn.Identifier] = newMember
p.Unlock()
}
}
我将->>>>>>
放在正在访问2段代码的位置旁边,我不确定如何在不进行数据竞争的情况下保持这些2更新,相当新的想知道如何在没有数据竞争的情况下阅读和编写这个变量。
答案 0 :(得分:1)
您的问题中有很多代码,但看起来您正在尝试从一个goroutine中的地图(party.Members
)中删除元素,而在另一个goroutine中将其循环。这听起来像是一场难以维持,错误缠身的灾难,但是没有记忆比赛就可以做到。
您需要一个互斥锁来保护对地图的访问(包括读取和写入),而困难的部分是确保在for/range
迭代期间保持锁定。这是一种方法,通过在for
循环开始之前保持锁定,并在循环体内解锁它。
var mut sync.Mutex
var m = map[string]int{}
func f(key string) {
mut.Lock()
defer mut.Unlock()
delete(m, key)
}
func g() {
mut.Lock()
defer mut.Unlock()
for k, v := range m {
mut.Unlock()
fmt.Println(k, v)
mut.Lock()
}
}
此处,f
和g
的任意组合可以在没有记忆竞赛的情况下同时调用。
理解上更简单的是不解锁/锁定循环内的互斥锁,这意味着f
中的删除会等待g
中的任何正在运行的循环完成(反之亦然) )。