liveBook · Manning

Shared-memory interprocess communication

As explained in Learn Concurrent Programming with Go

Memory sharing is a communication approach in which concurrent executions exchange information by accessing common memory.

Shared-memory interprocess communication lets concurrent executions exchange information by reading and writing a common memory location. A shared variable, slice, or other data structure becomes the collaboration surface: one execution records a result and another can observe or update it. For threads in one process, this resembles a shared whiteboard rather than sending messages back and forth. section 3.0 section 3.1

Figure 3.1 Communication via memory sharing

Use the whiteboard diagram to distinguish shared-memory communication from message passing: participants coordinate through one common state rather than explicit messages. section 3.1

Sharing memory is simple to start: allocate data, pass a reference to concurrent work, and let each execution access that location. It is not automatically safe. Execution order is nondeterministic, so a value written by one goroutine can change before another reads it. On multicore systems, caches and memory architecture add further complexity to how shared updates are observed. section 3.1 section 3.2.3

Use shared memory deliberately, with these constraints in mind:

  • Protect critical sections—instructions that must run without interference—with proper synchronization; otherwise shared access can produce race conditions and unexpected results. section 3.5 section 9.1
  • Do not rely on scheduling behavior to fix a race. Race conditions can vary between runs and are difficult to reproduce; use Go's race detector to help find them. section 3.5
  • Expect shared-memory designs to expose less obvious data flow and often require mutexes, semaphores, or other protected regions, making them harder to read than message-passing designs. section 8.2.1
  • Consider it when copying large data or exchanging many messages would make channel-based communication costly, while accounting for synchronization complexity. section 8.2.4 section 8.4

A countdown shared by two goroutines

Allocate an integer count, start a countdown goroutine with a pointer to it, and repeatedly print count from main. The countdown decrements the same location once per second while main reads it every half second, so repeated values appear in the output. Removing the go keyword makes the work sequential: countdown finishes before main begins its printing loop. section 3.2.1

Concurrent letter-frequency counting

Thirty-one goroutines can download separate web pages while updating one shared 26-element frequency slice. Downloads finish sooner and completion messages arrive out of order, but unsynchronized increments lose updates, producing lower and run-dependent character totals than the sequential version. section 3.2.3

Message passing is the main alternative. Channels isolate each goroutine's state and make inputs and outputs clearer, which often supports simpler and more loosely coupled designs. Shared memory may reduce copying and memory use, but it also tends to couple executions through common mutable state. Avoid mixing the two styles casually: passing mutable pointers on channels can reintroduce shared-memory races. section 8.2.2 section 8.2.3 section 9.2

How Learn Concurrent Programming with Go covers it

How deep it goes
Explains pointer and slice sharing through runnable examples, race outcomes, hardware caches, synchronization needs, and design trade-offs.
Examples
Demonstrates a shared countdown variable and concurrent web-page letter counting with a shared frequency slice.
What it assumes
Assumes Go or a similar C-style language while introducing concurrency concepts and classic synchronization primitives from a gentle starting point.
What you can do after
Evaluate/understand when shared state needs synchronization and when message passing better fits performance, memory, or maintainability constraints.
How it connects
Connects memory sharing to race conditions, critical sections, mutexes, semaphores, channels, message passing, and loose coupling.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Concurrent Programming with Go. The section links point to the parts of the book it draws on.