March 2017: Concurrency

Meetup #37. Please RSVP at Meetup.

We get started at 6:30 pm.

Sponsors

Venue provided by Startup Edmonton.

Food sponsored by Bellstone Engineering.

Talks

Goroutines

Nathan Youngman gave a gentle introduction to goroutines. He began with hello world and added the go keyword, then used a time.Sleep to show why a program can exit before a goroutine finishes. From there he placed goroutines in context: a process, OS threads, coroutines (cooperative multi-threading managed by a runtime or library), and finally goroutines — which multiplex independently executing functions (coroutines) onto a set of OS threads. He finished with sync.WaitGroup as the way to wait for goroutines to complete.

Key points:

  • A goroutine is started with the go keyword.
  • Sleeping is a crude way to let goroutines run before exit.
  • Processes, threads, and coroutines provide the background.
  • Goroutines multiplex coroutines onto OS threads.
  • sync.WaitGroup is the idiomatic way to wait for goroutines.

slides

Un-Paralleled Concurrency

Gerrit Renker gave a tour of basic concurrency patterns in Go, built around the proverb "concurrency is not parallelism." He contrasted the classic model of communicating by sharing memory (threads plus mutexes, hard to reason about) with Go's share-memory-by-communicating model based on CSP, and covered channels as FIFO reference types with directional variants. The talk progressed from generators and pipelines through buffered channels, then multiplexing with select. Along the way he demonstrated synchronization signals (empty structs and closed channels), broadcast via closed channels, writer/reader patterns (1:1, 1:n fan-out, n:1 fastest-response-first), the bounded-buffer/counting-semaphore pattern, and cleaning up goroutine leaks. Advanced patterns included futures, a monitor goroutine, and an implementation of the actor model as a goroutine plus a channel mailbox.

Key points:

  • Go favours 'share memory by communicating' over shared memory + mutexes.
  • Channels are FIFO and can be send-only or receive-only.
  • Unbuffered channels synchronize sender and receiver.
  • Closing a channel broadcasts a signal to all receivers.
  • Buffered channels enable bounded buffers and counting semaphores.
  • select handles timeouts, heartbeats, and message loops.
  • Advanced patterns: futures, monitor goroutines, and the actor model.

slides

Gotrace

Concurrency tracer and visualizer (source) demonstration by Matthias Stone

The atomic package

Lukasz Rozycki gave an overview of the sync/atomic package. He started with a bank-withdrawal example to show how interleaved statements race: two goroutines both read a balance of 150, both pass the >= amount check, and the balance ends up wrong — a data race the detector will catch. The only operations Go guarantees to be atomic live in sync/atomic, and he walked through its families: AddT (atomic *addr += delta), LoadT/StoreT (to avoid torn reads and writes), SwapT, and CompareAndSwapT (the basis for lock-free loops). He used an HTTP request counter to demonstrate each, then covered atomic.Value, which atomically loads and stores a consistently typed value, with a config-reload example and a read-mostly map updated by copy-on-write.

Key points:

  • Plain reads/modifies/writes can interleave into data races.
  • Only sync/atomic operations are guaranteed atomic.
  • AddT atomically adds and returns the new value.
  • LoadT/StoreT prevent torn reads and writes.
  • SwapT returns the old value while storing a new one.
  • CompareAndSwapT enables lock-free compare-and-swap loops.
  • atomic.Value stores a typed value safely, ideal for config reloads.

slides

News

Events