Unfortunately, that's not how Go maps work. You'll still get races unless you synchronize even "read-only" maps.
On Tuesday, February 22, 2022 at 11:59:37 PM UTC-6 ren...@ix.netcom.com wrote: > The top level map locks doesn’t matter - it is write once at init and read > only after. > > On Feb 22, 2022, at 11:51 PM, Jason E. Aten <j.e....@gmail.com> wrote: > > You have not synchronized access to the top level mapLocks map itself. > Thus you will get races. You need to have a mutex that you lock before you > access mapLocks; not just the maps that are inside it. > > > I would also recommend being a little object oriented about this design, > putting each map inside its own struct, and make a set of accessor methods > that Lock() and defer Unlock() on a mutex that protects the maps inside. > Read code like this for an idea of what I mean. > https://github.com/glycerine/atomicmap/blob/master/amap.go > > On Tuesday, February 22, 2022 at 9:55:04 PM UTC-6 ren...@ix.netcom.com > wrote: > >> Something else is wrong - because marketMaps is read-only after init… so >> unless you have some other code - that is not the map causing the panic. >> >> My guess is because you are returning the map from ReadMaps (or RWMaps) >> that you are using THAT map by multiple threads outside the lock (the map >> is a reference not a copy) and that is causing the panic. >> >> On Feb 22, 2022, at 9:39 PM, Zhaoxun Yan <yan.z...@gmail.com> wrote: >> >> Hi guys! >> I know this is quite challenging, but it makes sense in io-heavy >> applications. >> >> I need to test the responsiveness of different financial future quotation >> sources. They return the quotations spontaneously, and my program respond >> to each one of the CGO call backs from the quotation library and save the >> current prices. Meanwhile, a timer ensures to check the current quotations >> of each available sources. And obviously, it raised up a panic due to >> synchronization of maps on the call of ReadMaps function. Unfortunately >> this came up occasionally and `go build -race` cannot raise the problem. >> >> Here is a piece of the code, only the read/write part: >> >> >> ------------------------------------------------------------------------------------------ >> >> // Please Ignore SyChan to alert the timer that all available sources are >> collected >> var SyChan chan int = make(chan int, 3) >> >> // Make up a map of 5 mutex locks and a map of 5 data structs, indexed by >> 1-5 >> var marketMaps = make(map[int]map[string]Market) >> var mapLocks = make(map[int]*sync.Mutex) >> >> // quotation data >> type Market struct { >> Price float64 `json:"price"` >> Timestamp string `json:"timestamp"` >> } >> >> func init() { >> for i := 1; i <= 5; i++ { >> mapLocks[i] = new(sync.Mutex) >> marketMaps[i] = make(map[string]Market) >> } >> } >> >> //Make sure that for each source, R/W has no race, only took place as >> acquiring the particular Mutex inside the map of Mutex. >> func RWMaps(targetnum int, purpose, future_id string, market Market) >> map[string]Market { >> >> mapLocks[targetnum].Lock() >> defer mapLocks[targetnum].Unlock() >> >> if purpose == "update" {//The original Write part >> marketMaps[targetnum][future_id] = market >> return nil >> } else { //The read part, has been extracted to ReadMaps >> SyChan <- 1 >> return marketMaps[targetnum] >> } >> } >> >> //Here is why I use map: not all 5 sources must be available, some may >> have connection failure and would be marked as false in Usable[i] , i being >> its source No. >> func ReadMaps(targetnum, checkTime int) map[string]Market { >> mapLocks[targetnum].Lock() >> defer mapLocks[targetnum].Unlock() >> if Usable[targetnum] { >> fmt.Printf("%d-th time to read source %d \n", checkTime, >> targetnum) >> } >> SyChan <- 1 >> return marketMaps[targetnum] >> } >> >> >> -------------------------------------------------------------------------------------------------- >> >> My problem is : >> >> I still want to keep the map structure, rather than naming mutex1, >> mutex2, mutex3,... , marketmsg1, marketmsg2, .... And obviously if the map >> prohibits reading or writing spontaneously, the writing by each usable >> sources is not fair - They must line up as one queue (like using one Mutex >> for all instead) hence the checking of quotation snap on a time-spot is >> defected. I have also checked the sync.Map and it seems to allow >> spontaneous reading but still prohibits spontaneous writing. >> >> My instinct is to make map on the pointer of structs. On that way, if I >> could use sync.Map, both the read and write function only read the map to >> find the address of data structs, then writing several data structs on the >> same time won't violate the rule on sync.Map. >> >> Is the proposal above legitimate? And anyone could come up a test case to >> mimic the quotation sources? Because with CGO to complicate the program, go >> cannot raise the race problem on -race check, and the successful build can >> panic occasionally. >> >> Thanks in advance! >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/9a981200-23f8-4dae-8c20-7acfdcd3f2fcn%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/9a981200-23f8-4dae-8c20-7acfdcd3f2fcn%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> >> -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/215a541a-ecc6-49e2-9427-81f62c5b168en%40googlegroups.com > > <https://groups.google.com/d/msgid/golang-nuts/215a541a-ecc6-49e2-9427-81f62c5b168en%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0b709930-8fbb-4fce-8cdf-0cf3bb401d22n%40googlegroups.com.