嗨,大家好我正在尝试使用websockets创建一个派对系统,人们可以进入队列,然后匹配5个与他们相似的人.现在我遇到这个部分有问题:
type PartyHub struct {
Partys map[string]*Party
PartialPartys []*PartialParty
Queue []*Member
AddParty chan *Party
RemoveParty chan *Party
AddPartialParty chan *PartialParty
RemovePartialParty chan *PartialParty
EnterQueue chan *Member
LeaveQueue chan *Member
Mu sync.Mutex
}
// Run will begin monitoring the channels
// to register and unregister partys as they are
// created or destroyed
func (p *PartyHub) Run() {
for {
select {
case member := <-p.EnterQueue:
go p.SortMemberIntoParty(member)
go p.SortMemberIntoParty(member)
go p.SortMemberIntoParty(member)
go p.SortMemberIntoParty(member)
go p.SortMemberIntoParty(member)
log.Println(p.PartialPartys)
case party := <-p.AddPartialParty:
p.Mu.Lock()
defer p.Mu.Unlock()
p.PartialPartys = append(p.PartialPartys, party)
}
}
}
// SortMemberIntoParty will take a new user entering the queue and find an appropriate Party
// for the member to join, taking into account RankTollerance, Rank
func (p *PartyHub) SortMemberIntoParty(member *Member) {
p.Mu.Lock()
defer p.Mu.Unlock()
if len(p.PartialPartys) == 0 {
log.Println("Here")
newParty := &PartialParty{Accepting: true, Members: []*Member{member}}
p.AddPartialParty <- newParty
return
}
foundPartyForMember := false
for _, party := range p.PartialPartys {
goodFitForParty := true
for _, partyMember := range party.Members {
log.Println(member.Type == partyMember.Type, member.Rank >= partyMember.Rank-partyMember.RankTol, member.Rank <= partyMember.Rank+partyMember.RankTol)
if member.Type == partyMember.Type && member.Rank >= partyMember.Rank-partyMember.RankTol && member.Rank <= partyMember.Rank+partyMember.RankTol {
goodFitForParty = true
continue
} else {
goodFitForParty = false
break
}
}
if !goodFitForParty {
continue
} else {
foundPartyForMember = true
party.Mu.Lock()
defer party.Mu.Unlock()
party.Members = append(party.Members, member)
if len(party.Members) == 5 {
party.Accepting = false
go party.SendReadyCheck()
}
break
}
}
if !foundPartyForMember {
newParty := &PartialParty{Accepting: true, Members: []*Member{member}}
p.AddPartialParty <- newParty
}
log.Println("Sorting Members")
}
Run Code Online (Sandbox Code Playgroud)
唯一的问题是,5 goroutines似乎比数据知道发生了什么更快完成.
例如:p.PartialPartys说它没有派对.
我需要的是p.PartialPartys每个goroutine访问PartyHub结构域的每个人都是最新的我虽然sync.Mutex会为我做这个但是似乎不是这样,有人能告诉我最好的方法来保留我所有的goroutines与同一数据同步?
因此,通过这种实现,您的五个goroutine都不能并行运行,因为它们都试图释放p.Mu互斥锁.看看你使用p.AddPartialParty频道的方式,如果代码可以死锁,我也不会感到惊讶.
考虑以下事件序列:
SortMemberIntoPartygoroutines开始运行并获得互斥锁.p.AddPartialParty,由...接收Run. Run然后试图获取互斥锁,所以阻止.SortMemberIntoPartygoroutine完成并释放互斥锁.SortMemberIntoPartygoroutine获取互斥锁,并尝试发送另一个值p.AddPartialParty.Run在返回select语句之前仍在等待互斥锁).所以现在你有一个阻塞的goroutine,持有通道接收端所需的锁.另请注意,在(4)您将看不到新的,PartialParty因为Run还没有设法添加它.
如果你确实需要互斥锁,那么直接进行SortMemberIntoPartygoroutine更新可能p.PartialPartys比使用频道更容易:你已经知道没有其他人会同时访问变量.
值得记住的是,这个互斥锁本质上意味着所有SortMemberIntoPartygoroutine都将被序列化.如果你正在使用goroutines以期在这里实现并行性,那么互斥体就会失败.
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |