On Tue, Apr 14, 2020 at 4:39 AM Slawomir Pryczek <slawek1...@gmail.com> wrote: > > Hi Guys, was wondering about some things related to multithread code. > > 1. If data that is accessed or changed - it needs to go into CPU cache first, > and AFAIK to caches whole memory block not just this single area of memory on > which we're operating. When we're doing writes without synchronization to > something which is tightly packed, how does it work that cache isn't > poisoned, and the result is still correct, even if each cpu core is having > its own L1 and L2 caches?
If you use atomic writes, the CPU cores will communicate to either invalidate cache lines or provide an update of the new memory contents. On x86 this happens even if you don't do an atomic write. On some other processors, the other CPU cores can see old data in that memory address for some period of time. > Are such patterns, when single thread is only operating on single cell(s) of > memory, considered thread safe for slices and in general? > https://play.golang.org/p/rF8jPEGDZzk As far as I know this is safe on all modern multi-core processors. They will use cache snooping or other techniques to make sure that at most one core has a dirty version of a particular cache line. Of course, if there are many cores the performance can be quite bad. > 2. For lazy initialization double-check pattern. I found on several sources > that it is safe, still race detector complains about data races (which is > correct because there is race, which is done on purpose) - > https://software.intel.com/en-us/node/506123 > And of course this code seems to be working as expected > > https://play.golang.org/p/gUzWHr-1K9H This is unsafe in general because nothing ensures that memory changes made before setting initialized to true are visible to other cores that happen to see initialized set to true. That is, in your example, some other core could see the variable initialized set to true without seeing any values stored in the variable myconfig. That can't happen on x86, which enforces memory ordering of writes, but it can happen on other non-x86 processors. Note that I think that your link to software.intel.com doesn't support your argument even on x86, as in that link they are using atomic writes, but your code is using ordinary writes. > 3. Now question is, can i disable these warnings somehow so race detector > won't complain about safe code because i have ton of these and it's > obfuscating usable output? No. Your code isn't safe, and the race detector should and will complain. > 4. Im not sure about instruction ordering, will it always be the case that > threads that see initialized=true will also see myconfig AFTER the update, > because myconfig isn't synchronized. Would it be better to just use pointer > instead and check for nil value or even atomic.Value? It would be better to use a sync.Mutex or, if absolutely necessary, use the calls in the sync/atomic package. > 5. How these patterns are working with other CPUs, are they considered unsafe > on anything other than intel architecture? As noted Intel architectures enforce a global write ordering. That is not true on most other multi-core processors. > So im writing some code which will do hundreds of thousands of operations per > second and these operations need to read config (probably in some cases at > multiple places). You think using just atomic.Value (Store/Load) will have > impact when i run it on machine with eg. 96 cores? Maybe RW mutex would be > better? What you think? I could just run some synthetic benchmarks but for > these usually seem to not have much use in real life scenarios for > multithreaded code. I agree that synthetic benchmarks are unlikely to help. You'll have to benchmark your real code. There is no single answer as to what is best as it depends on things like the number of reads compared to the number of writes, and what happens if you use out of date data, and what is driving your operations. For example, in Go, if your operations are being driven by channel data, and if it doesn't matter if you use slightly out of date configuration information, then it's easy enough to send configuration updates on a channel and have the workers use select to pick up either the next data item or the configuration change. I don't know whether that makes any sense for your situation. Ian -- 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/CAOyqgcUmptjAYSqCa5OP5%2B5xmhEw6mzYgu7PX%3D1ouGbp-Sttyw%40mail.gmail.com.