Use a slice instead of a map ? Jason E. Aten a következőt írta (2022. február 23., szerda, 7:10:04 UTC+1):
> 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 [email protected] > 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 <[email protected]> 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 [email protected] >> 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 <[email protected]> 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 [email protected]. >>> 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 [email protected]. >> >> 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/26d16145-9473-42a5-aa76-80dbe18313b7n%40googlegroups.com.
