I read O’REILLY’s “Concurrency in Go” and am leaving notes for myself. Also, I’ve compiled useful functions for concurrent processing based on the ideas in the book at https://godoc.org/github.com/bobuhiro11/gostream.
- Race conditions occur when two or more operations must be executed in the correct order, but the program doesn’t guarantee that order.
- We should aim for logical correctness, and cannot solve it by methods like inserting Sleep functions.
- The necessary conditions for deadlock are known as the Coffman conditions.
- In the author’s opinion, livelock is harder to detect than deadlock. It can’t be detected by observing resource usage from outside the program.
- Functions involved in concurrency should have appropriate comments. Describe who is responsible for concurrency, what kind of concurrency primitives it corresponds to, and who is responsible for synchronization. Function signatures are insufficient.
- Concurrency is a property of code, parallelism is a property of a running program.
- Go’s concurrency primitives were designed based on Tony Hoare’s “Communicating Sequential Processes”.
- Besides CSP, you can also write code for traditional memory access synchronization. These are collected in the
syncpackage. - However, in Go programming style, using high-level techniques is recommended. At any given moment, only one goroutine should handle specific data.
- Instead of sharing memory, communicate via channels.
- Besides CSP, you can also write code for traditional memory access synchronization. These are collected in the
- You can estimate the number of goroutines that can be created based on memory size. According to examples in the text, with 8GB RAM, you can create millions of goroutines.
- Calls to
Addinsync.WaitGroupshould be written as close as possible to the goroutine being monitored. - To avoid deadlocks, when using
Mutex, make theUnlockcall in adeferstatement. RWMutexis more advanced thanMutex. Multiple read locks can be acquired if no one holds a write lock.- Buffered channels tend to lead to premature optimization. Deadlocks become invisible.
- Keep the scope of channel ownership small.
- The Go runtime makes a uniform pseudo-random selection across all
casestatements. - An empty
selectstatementselect {}blocks forever. - The concept of confinement ensures that information can only be obtained from a single concurrent process.
// The write scope to the channel is lexically confined within the function.
func owner() <-chan int {
c := make(chan int)
go func() {
defer close(c)
for i:=0; i<10; i++ {
c <- i
}
}()
return c
}
- Introducing queues into a system is convenient, but it can lead to premature optimization. The benefit of introducing queues is not that stage execution time decreases, but that the time stages spend blocked decreases.
- For queues, throughput can be predicted using Little’s Law.
- Pass
contextas the first argument of functions. Don’t use it to store references to frequently used data. - Heartbeats are not always necessary. They are useful for long-running operations.