douxi0098 2015-12-26 06:28
浏览 14

我如何摆脱这种数据竞争

I have these 2 functions:

// 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()
    }
}

I put ->>>>>> next to where the 2 pieces of code are being accessed, I'm not sure how I can keep these 2 up to date without being in a data race, fairly new to go and wondering how I should be reading and writing this variable without a data-race.

  • 写回答

1条回答 默认 最新

  • duanjing1276 2015-12-26 07:49
    关注

    You've got a lot of code in your question, but it looks like you're trying to delete elements from a map (party.Members) in one goroutine, while looping over it in another. This sounds like an unmaintainable, error-ridden disaster in the making, but it's possible to do without memory races.

    You need a mutex to protect access (both read and write) to the map, and the hard part is to make sure the lock is held during the for/range iteration. Here's one way to do it, by having the lock held before the for loop starts, and unlocking it inside the body of the loop.

    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()
        }
    }
    

    Here, any combination of fs and gs can be called concurrently without memory races.

    Drastically simpler to understand would be to not Unlock/Lock the mutex inside the loop, which would mean a deletion in f would wait for any running loop in g to complete (or vice-versa).

    评论

报告相同问题?

悬赏问题

  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探