The thing to remember is: You have a data race if there are multiple accesses to the same address, at least one of which is a write.
There are techniques that help you avoid data races, using high-level abstractions, like e.g. “don’t ever overwrite memory”, aka persistent/functional datastructures, or “mutating threads have exclusive ownership”, aka “there is no way of accessing the object from other threads”. In some languages like e.g. Rust, there is a lot of compiler support to help you not mess up.
Since abstract high-level techniques have a tendency to either incur high runtime costs, or involve lots of decorum, it is totally fine to just write data-race free code without any abstraction to help you. This is not a code smell.
But the above low-level definition of “race condition” doesn’t play nice with abstractions like AbstractVector
.
So by opting in to the more fine-grained view of data races, you require that yourself and all future readers / maintainers of your code pierce the veil of abstractions, and don’t think about “mutate an object” but rather think about “issue the following store to memory”, i.e. keep the generated @code_llvm
/ @code_native
in mind (otherwise they will shoot themselves with concurrent modification of BitArray, SparseArray, Dict, etc).
I personally think that this is appropriate for julia: It is not a deeply specced virtual machine, it is a tool + runtime to conveniently express the code you want, where you are both empowered and required to fluently switch between high-level (“mutate that thing!”) and low-level (“these two memory accesses don’t alias”) and very low-level (micro-architectural, “these two memory accesses hit the same cache line from multiple threads, so will be slow!”, “this branch is predictable, so better avoid CMOV!”).
But opinions differ on that, some people prefer code that doesn’t need an understanding of low level
This especially affects documentation: The authors of things like OhMyThreads docs are in a permanent conundrum about whether to stick to high-level rules of thumb, which exclude lots of good code, or to give the more nuanced low-level view, which excludes all programmers who don’t have at least a very basic knowledge of assembly / low-level.
I think the docstring you quoted is pretty ideal: They recommend something for newbies, together with references to learn more, and enough nuance for more seasoned users to know when to disregard the recommendation.