Concurrency in Go
Concurrency in Go
Concurrency in Go
Programming Model
Mostly CSP/-calaculus (not actually formalized): goroutines+channels Go concurrency motto:
Goroutines
Think threads (however no join operation) go foo() go logger.Printf("Hello, %s!", who) go func() { logger.Printf("Hello, %s!", who) ... }()
Channels
Basically typed bounded blocking FIFO queues. // synchronous chan of ints c := make(chan int) // buffered chan of pointers to Request c := make(chan *Request, 100)
Channels: input/output
func foo(c chan int) { c <- 0 <-c } func bar(c <-chan int) { <-c } func baz(c chan<- int) { c <- 0 }
Channels: closing
func producer(c chan *Work) { defer close(c) for { work, ok := getWork() if !ok { return } c <- work } }
Select
Select makes a pseudo-random choice which of a set of possible communications will proceed: select { case c1 <- foo: case m := <-c2: doSomething(m) case m := <-c3: doSomethingElse(m) default: doDefault() }
Select: timeouts
select { case c <- foo: case <-time.After(1e9): }
Mutexes
sync.Mutex is actually a cooperative binary semaphore - no ownership, no recursion. mtx.Lock() go func() { ... mtx.Unlock() } mtx.Lock() func foo() { mtx.Lock() defer mtx.Unlock() ... }
General Scheme
90% of CSP on higher levels +10% of Shared Memory on lower levels
Scalability
The goal of Go is to support scalable fine-grained concurrency. But it is [was] not yet there. Submitted about 50 scalability-related CLs. Rewrote all sync primitives (mutex, semaphore, once, etc), improve scalability of chan/select, memory allocation, stack mgmt, etc. "I've just run a real world benchmark provided by someone using mgo with the r59 release, and it took about 5 seconds out of 20, without any changes in the code." Still to improve goroutine scheduler.
Thanks!