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
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
