Occam is probably the most important totally forgotten thread of programming language development.
I would suggest reviewing the Hoare book on CSP, it’s very readable.
I'm not an OS expert but I've worked with distributed systems and threads for decades, and nobody I've asked has disagreed that Go's implementation of CSP is an M:N thread model with (blocking) queues.
BUFFER = P⟨⟩
where
P⟨⟩ = left?x → P⟨x⟩
P⟨x⟩⌢s = (left?y → P⟨x⟩⌢s⌢⟨y⟩
| right!x → Ps )
If data can be read from left it is and it's enqueued, if data can be written to right (because a reader is available) it dequeues it. But neither the read nor the write block the entire process.Go's buffered channels act in the same way so end up offering a shortcut versus pure CSP. There are other ways that Go deviates from CSP (shared memory, among others) but with channels it's not deviating, just optimizing an existing behavior.
I'm not downplaying anything; I'm expressing merely that with a title like "Goroutines: The concurrency model we all..." makes it sounds like go invented something new, but afaict, they're just a well-engineered implemention of already well-understood concurrency principles.
When it comes to concurrency I think it's good to go through the curriculum:
- main loop + interrupt handler
- processes (fork)
- multi-core concerns
- threads (now is a good time to learn about mutex, semaphore, critical section)
- lightweight threads (fiber, coroutines, green threads): learn how they are different
- async/await statemachines written by the compiler
Ok, now we have the background info to make wise choices and call things by their generalized names to avoid holy wars.
We could use a time-faking library, but sometimes this is unavoidable if some dependency, whether from a 3rd party or in stdlib, depends on reliable timing.
I'm wondering how other Go devs approach this.
https://go.dev/doc/articles/race_detector https://go.dev/blog/race-detector
It only logs when a race condition happens, and it may have a non-negligible impact on performance, but it should print useful info to aid in debugging.
A solution would be to run CI on self-managed nodes that behave more reliably, but that has maintenance costs that we don't want to deal with.