That is not correct.

See https://go.dev/play/p/aZ7LostRuKR 

You can run this under the race detector without failure.

Still, the race detector cannot detect all races so better to look at the 
source for sync.Map at 105 
<https://cs.opensource.google/go/go/+/master:src/sync/map.go;drc=2580d0e08d5e9f979b943758d3c49877fb2324cb;l=105>

You can see that it reads the underlying shared maps while not under 
lock/exclusive access.

Starting a go routine creates a “happens before” relationship which allows this 
to work.

> On Feb 23, 2022, at 12:10 AM, Jason E. Aten <j.e.a...@gmail.com> wrote:
> 
> 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 
>> <applewebdata://5154297F-AADE-4DDF-B6C1-9D23F74248D4>> 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 
>> <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 
>> <applewebdata://5154297F-AADE-4DDF-B6C1-9D23F74248D4> 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 
>> <applewebdata://5154297F-AADE-4DDF-B6C1-9D23F74248D4>.
> 
>> 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 
> <mailto: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
>  
> <https://groups.google.com/d/msgid/golang-nuts/0b709930-8fbb-4fce-8cdf-0cf3bb401d22n%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/A04B8C4C-3C0C-4077-9FCF-5632D359C664%40ix.netcom.com.

Reply via email to