I have a struct defined as follows:
type transactionList map[string]Transaction
type ActiveTransactions struct {
mtx sync.Mutex
trm transactionList
}
This struct has several methods defined:
func (act *ActiveTransactions) NewTransaction(id string, myPayload Payload) {
act.mtx.Lock()
act.trm[id] = Transaction{currentState: FirstState, Payload: myPayload}
act.mtx.Unlock()
}
func (act *ActiveTransactions) GetState(id string) TState {
act.mtx.Lock()
state := act.trm[id].currentState
act.mtx.Unlock()
return state
}
func (act *ActiveTransactions) UpdateState(id string, newState TState) {
act.mtx.Lock()
tmp := act.trm[id]
tmp.currentState = newState
act.trm[id] = tmp
act.mtx.Unlock()
}
This type is created once and is accessed by multiple goroutines. When I run the code it occasionally panics because of concurrent read/write map access (which is not entirely clear to me since access to the map is protected with sync.Mutex
).
I have tried to run the code with -race option and it detects race condition as well (from the -race output I can see that race happens for GetState and NewTransaction methods)
What's happening here? Should trm be protected by mtx once Lock()
is called? From the examples, I searched in the docs and tutorials the pattern looks ok. Obviously, something is wrong, but it eludes me.