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.
>> 
> 
> -- 
> 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.

-- 
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/87176801-8735-4312-BBD4-42AF49979F1C%40ix.netcom.com.

Reply via email to