I'm writing some program in Go, I get this crash:
fatal error: concurrent map read and map write
consensus/bft.(*ConsensusManager).getHeightManager(0xc42009a7e0, 0x37, 0x0)
consensus/bft/bft_manager.go:246 +0x9b fp=0xc42b033258 sp=0xc42b033208 pc=0xaf1d7b
consensus/bft.(*HeightManager).Round(...)
consensus/bft/bft_manager.go:239
consensus/bft.(*ConsensusManager).Round(0xc42009a7e0, 0x37)
This is my code
type ConsensusManager struct {
pm *ProtocolManager
chain *core.BlockChain
coinbase common.Address
readyValidators map[common.Address]struct{}
trackedProtocolFailures []string
heights map[uint64]*HeightManager
blockCandidates map[common.Hash]btypes.Proposal
currentBlock *types.Block
found chan *types.Block
mu sync.Mutex
writeMapMu sync.RWMutex
getHeightMu sync.RWMutex
processMu sync.Mutex
}
func (cm *ConsensusManager) Round() uint64 {
return cm.getHeightManager(cm.Height()).Round()
}
func (cm *ConsensusManager) getHeightManager(h uint64) *HeightManager {
if _, ok := cm.heights[h]; !ok {
cm.heights[h] = NewHeightManager(cm, h)
}
return cm.heights[h]
}
I try to Use RWMutex to Luck, but the code can't work
func (cm *ConsensusManager) Round() uint64 {
cm.getHeightMu.Lock()
defer cm.getHeightMu.Unlock()
return cm.getHeightManager(cm.Height()).Round()
}
func (cm *ConsensusManager) getHeightManager(h uint64) *HeightManager {
cm.getHeightMu.Lock()
defer cm.getHeightMu.Unlock()
if _, ok := cm.heights[h]; !ok {
cm.heights[h] = NewHeightManager(cm, h)
}
return cm.heights[h]
}
What's wrong with my solutions?