Overview
Using Go to lightly observe process address spaces, goroutine behavior, stack, and heap.
Checking Differences Between Child Processes and Address Spaces
In Go, new processes are typically launched using the os/exec package. Internally, os/exec performs operations equivalent to fork() + exec() on Unix-like OSes to execute a new program (in this example, itself).
Display the addresses of the same variables in parent and child processes to confirm the independence of memory spaces.
Meaning of Execution Results
-
Process Isolation: Different PIDs are displayed for parent and child.
-
Address Space Independence:
- Both the global variable
globalVarand the local variablelocalVarshow different addresses in parent and child. - This is because Unix-like OSes allocate independent virtual address spaces for each process. Although the numbers may appear similar, they are completely separate in physical memory.
- Both the global variable
Diagram of Memory Spaces Between Processes
Observing Goroutines and Memory Sharing
Using Go's lightweight threads, goroutines, to observe memory. Since goroutines operate within the same process, they share the virtual address space. To confirm this, display the addresses of global and local variables across multiple goroutines.
Analysis
- Same PID All goroutines operate within the same process, so the PID is identical.
- Global Variable Sharing
The address of
globalVaris the same across all goroutines. - Local Variable Independence
Each goroutine has an independent stack, but in this example, the address of
localVaris obtained and passed tofmt.Printf, causing it to escape to the heap. Even so, each goroutine is allocated a separate memory region, maintaining independence. - Data Race
The value of
globalVarbecoming 106 is coincidental; the result varies depending on execution timing. To safely perform concurrent processing, synchronization mechanisms like channels or mutexes are required. → Usego run -raceto detect race conditions.
Diagram of Memory Sharing Between Goroutines
Safe Concurrent Processing Using Goroutines and Channels
Using channels allows data exchange without directly updating shared variables.
Heap Area and Garbage Collection
In Go, dynamic memory is often placed in the heap, but the placement can be confirmed via escape analysis.
- The heap area is managed by GC, and explicit deallocation is unnecessary.
Differences Between Stack and Heap
| Item | Stack | Heap |
|---|---|---|
| Management | Automatically allocated/released with function calls | Managed by GC |
| Independence | Independent per goroutine | Shared across the process |
| Speed | Fast | Relatively slower |
| Placement | Non-escaping variables | Escaping variables |
Summary
- Process Independence Child processes have separate virtual address spaces from parent processes, and variables are not shared.
- Goroutine Memory Sharing Goroutines operate within the same process, sharing global variables but maintaining independent stacks.
- Memory Management Characteristics Go automatically allocates stack and heap using escape analysis, and manages the heap with GC.