123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- <!--{
- "Title": "The Go Memory Model",
- "Subtitle": "Version of May 31, 2014",
- "Path": "/ref/mem"
- }-->
- <style>
- p.rule {
- font-style: italic;
- }
- span.event {
- font-style: italic;
- }
- </style>
- <h2>Introduction</h2>
- <p>
- The Go memory model specifies the conditions under which
- reads of a variable in one goroutine can be guaranteed to
- observe values produced by writes to the same variable in a different goroutine.
- </p>
- <h2>Advice</h2>
- <p>
- Programs that modify data being simultaneously accessed by multiple goroutines
- must serialize such access.
- </p>
- <p>
- To serialize access, protect the data with channel operations or other synchronization primitives
- such as those in the <a href="/pkg/sync/"><code>sync</code></a>
- and <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> packages.
- </p>
- <p>
- If you must read the rest of this document to understand the behavior of your program,
- you are being too clever.
- </p>
- <p>
- Don't be clever.
- </p>
- <h2>Happens Before</h2>
- <p>
- Within a single goroutine, reads and writes must behave
- as if they executed in the order specified by the program.
- That is, compilers and processors may reorder the reads and writes
- executed within a single goroutine only when the reordering
- does not change the behavior within that goroutine
- as defined by the language specification.
- Because of this reordering, the execution order observed
- by one goroutine may differ from the order perceived
- by another. For example, if one goroutine
- executes <code>a = 1; b = 2;</code>, another might observe
- the updated value of <code>b</code> before the updated value of <code>a</code>.
- </p>
- <p>
- To specify the requirements of reads and writes, we define
- <i>happens before</i>, a partial order on the execution
- of memory operations in a Go program. If event <span class="event">e<sub>1</sub></span> happens
- before event <span class="event">e<sub>2</sub></span>, then we say that <span class="event">e<sub>2</sub></span> happens after <span class="event">e<sub>1</sub></span>.
- Also, if <span class="event">e<sub>1</sub></span> does not happen before <span class="event">e<sub>2</sub></span> and does not happen
- after <span class="event">e<sub>2</sub></span>, then we say that <span class="event">e<sub>1</sub></span> and <span class="event">e<sub>2</sub></span> happen concurrently.
- </p>
- <p class="rule">
- Within a single goroutine, the happens-before order is the
- order expressed by the program.
- </p>
- <p>
- A read <span class="event">r</span> of a variable <code>v</code> is <i>allowed</i> to observe a write <span class="event">w</span> to <code>v</code>
- if both of the following hold:
- </p>
- <ol>
- <li><span class="event">r</span> does not happen before <span class="event">w</span>.</li>
- <li>There is no other write <span class="event">w'</span> to <code>v</code> that happens
- after <span class="event">w</span> but before <span class="event">r</span>.</li>
- </ol>
- <p>
- To guarantee that a read <span class="event">r</span> of a variable <code>v</code> observes a
- particular write <span class="event">w</span> to <code>v</code>, ensure that <span class="event">w</span> is the only
- write <span class="event">r</span> is allowed to observe.
- That is, <span class="event">r</span> is <i>guaranteed</i> to observe <span class="event">w</span> if both of the following hold:
- </p>
- <ol>
- <li><span class="event">w</span> happens before <span class="event">r</span>.</li>
- <li>Any other write to the shared variable <code>v</code>
- either happens before <span class="event">w</span> or after <span class="event">r</span>.</li>
- </ol>
- <p>
- This pair of conditions is stronger than the first pair;
- it requires that there are no other writes happening
- concurrently with <span class="event">w</span> or <span class="event">r</span>.
- </p>
- <p>
- Within a single goroutine,
- there is no concurrency, so the two definitions are equivalent:
- a read <span class="event">r</span> observes the value written by the most recent write <span class="event">w</span> to <code>v</code>.
- When multiple goroutines access a shared variable <code>v</code>,
- they must use synchronization events to establish
- happens-before conditions that ensure reads observe the
- desired writes.
- </p>
- <p>
- The initialization of variable <code>v</code> with the zero value
- for <code>v</code>'s type behaves as a write in the memory model.
- </p>
- <p>
- Reads and writes of values larger than a single machine word
- behave as multiple machine-word-sized operations in an
- unspecified order.
- </p>
- <h2>Synchronization</h2>
- <h3>Initialization</h3>
- <p>
- Program initialization runs in a single goroutine,
- but that goroutine may create other goroutines,
- which run concurrently.
- </p>
- <p class="rule">
- If a package <code>p</code> imports package <code>q</code>, the completion of
- <code>q</code>'s <code>init</code> functions happens before the start of any of <code>p</code>'s.
- </p>
- <p class="rule">
- The start of the function <code>main.main</code> happens after
- all <code>init</code> functions have finished.
- </p>
- <h3>Goroutine creation</h3>
- <p class="rule">
- The <code>go</code> statement that starts a new goroutine
- happens before the goroutine's execution begins.
- </p>
- <p>
- For example, in this program:
- </p>
- <pre>
- var a string
- func f() {
- print(a)
- }
- func hello() {
- a = "hello, world"
- go f()
- }
- </pre>
- <p>
- calling <code>hello</code> will print <code>"hello, world"</code>
- at some point in the future (perhaps after <code>hello</code> has returned).
- </p>
- <h3>Goroutine destruction</h3>
- <p>
- The exit of a goroutine is not guaranteed to happen before
- any event in the program. For example, in this program:
- </p>
- <pre>
- var a string
- func hello() {
- go func() { a = "hello" }()
- print(a)
- }
- </pre>
- <p>
- the assignment to <code>a</code> is not followed by
- any synchronization event, so it is not guaranteed to be
- observed by any other goroutine.
- In fact, an aggressive compiler might delete the entire <code>go</code> statement.
- </p>
- <p>
- If the effects of a goroutine must be observed by another goroutine,
- use a synchronization mechanism such as a lock or channel
- communication to establish a relative ordering.
- </p>
- <h3>Channel communication</h3>
- <p>
- Channel communication is the main method of synchronization
- between goroutines. Each send on a particular channel
- is matched to a corresponding receive from that channel,
- usually in a different goroutine.
- </p>
- <p class="rule">
- A send on a channel happens before the corresponding
- receive from that channel completes.
- </p>
- <p>
- This program:
- </p>
- <pre>
- var c = make(chan int, 10)
- var a string
- func f() {
- a = "hello, world"
- c <- 0
- }
- func main() {
- go f()
- <-c
- print(a)
- }
- </pre>
- <p>
- is guaranteed to print <code>"hello, world"</code>. The write to <code>a</code>
- happens before the send on <code>c</code>, which happens before
- the corresponding receive on <code>c</code> completes, which happens before
- the <code>print</code>.
- </p>
- <p class="rule">
- The closing of a channel happens before a receive that returns a zero value
- because the channel is closed.
- </p>
- <p>
- In the previous example, replacing
- <code>c <- 0</code> with <code>close(c)</code>
- yields a program with the same guaranteed behavior.
- </p>
- <p class="rule">
- A receive from an unbuffered channel happens before
- the send on that channel completes.
- </p>
- <p>
- This program (as above, but with the send and receive statements swapped and
- using an unbuffered channel):
- </p>
- <pre>
- var c = make(chan int)
- var a string
- func f() {
- a = "hello, world"
- <-c
- }
- </pre>
- <pre>
- func main() {
- go f()
- c <- 0
- print(a)
- }
- </pre>
- <p>
- is also guaranteed to print <code>"hello, world"</code>. The write to <code>a</code>
- happens before the receive on <code>c</code>, which happens before
- the corresponding send on <code>c</code> completes, which happens
- before the <code>print</code>.
- </p>
- <p>
- If the channel were buffered (e.g., <code>c = make(chan int, 1)</code>)
- then the program would not be guaranteed to print
- <code>"hello, world"</code>. (It might print the empty string,
- crash, or do something else.)
- </p>
- <p class="rule">
- The <i>k</i>th receive on a channel with capacity <i>C</i> happens before the <i>k</i>+<i>C</i>th send from that channel completes.
- </p>
- <p>
- This rule generalizes the previous rule to buffered channels.
- It allows a counting semaphore to be modeled by a buffered channel:
- the number of items in the channel corresponds to the number of active uses,
- the capacity of the channel corresponds to the maximum number of simultaneous uses,
- sending an item acquires the semaphore, and receiving an item releases
- the semaphore.
- This is a common idiom for limiting concurrency.
- </p>
- <p>
- This program starts a goroutine for every entry in the work list, but the
- goroutines coordinate using the <code>limit</code> channel to ensure
- that at most three are running work functions at a time.
- </p>
- <pre>
- var limit = make(chan int, 3)
- func main() {
- for _, w := range work {
- go func(w func()) {
- limit <- 1
- w()
- <-limit
- }(w)
- }
- select{}
- }
- </pre>
- <h3>Locks</h3>
- <p>
- The <code>sync</code> package implements two lock data types,
- <code>sync.Mutex</code> and <code>sync.RWMutex</code>.
- </p>
- <p class="rule">
- For any <code>sync.Mutex</code> or <code>sync.RWMutex</code> variable <code>l</code> and <i>n</i> < <i>m</i>,
- call <i>n</i> of <code>l.Unlock()</code> happens before call <i>m</i> of <code>l.Lock()</code> returns.
- </p>
- <p>
- This program:
- </p>
- <pre>
- var l sync.Mutex
- var a string
- func f() {
- a = "hello, world"
- l.Unlock()
- }
- func main() {
- l.Lock()
- go f()
- l.Lock()
- print(a)
- }
- </pre>
- <p>
- is guaranteed to print <code>"hello, world"</code>.
- The first call to <code>l.Unlock()</code> (in <code>f</code>) happens
- before the second call to <code>l.Lock()</code> (in <code>main</code>) returns,
- which happens before the <code>print</code>.
- </p>
- <p class="rule">
- For any call to <code>l.RLock</code> on a <code>sync.RWMutex</code> variable <code>l</code>,
- there is an <i>n</i> such that the <code>l.RLock</code> happens (returns) after call <i>n</i> to
- <code>l.Unlock</code> and the matching <code>l.RUnlock</code> happens
- before call <i>n</i>+1 to <code>l.Lock</code>.
- </p>
- <h3>Once</h3>
- <p>
- The <code>sync</code> package provides a safe mechanism for
- initialization in the presence of multiple goroutines
- through the use of the <code>Once</code> type.
- Multiple threads can execute <code>once.Do(f)</code> for a particular <code>f</code>,
- but only one will run <code>f()</code>, and the other calls block
- until <code>f()</code> has returned.
- </p>
- <p class="rule">
- A single call of <code>f()</code> from <code>once.Do(f)</code> happens (returns) before any call of <code>once.Do(f)</code> returns.
- </p>
- <p>
- In this program:
- </p>
- <pre>
- var a string
- var once sync.Once
- func setup() {
- a = "hello, world"
- }
- func doprint() {
- once.Do(setup)
- print(a)
- }
- func twoprint() {
- go doprint()
- go doprint()
- }
- </pre>
- <p>
- calling <code>twoprint</code> causes <code>"hello, world"</code> to be printed twice.
- The first call to <code>doprint</code> runs <code>setup</code> once.
- </p>
- <h2>Incorrect synchronization</h2>
- <p>
- Note that a read <span class="event">r</span> may observe the value written by a write <span class="event">w</span>
- that happens concurrently with <span class="event">r</span>.
- Even if this occurs, it does not imply that reads happening after <span class="event">r</span>
- will observe writes that happened before <span class="event">w</span>.
- </p>
- <p>
- In this program:
- </p>
- <pre>
- var a, b int
- func f() {
- a = 1
- b = 2
- }
- func g() {
- print(b)
- print(a)
- }
- func main() {
- go f()
- g()
- }
- </pre>
- <p>
- it can happen that <code>g</code> prints <code>2</code> and then <code>0</code>.
- </p>
- <p>
- This fact invalidates a few common idioms.
- </p>
- <p>
- Double-checked locking is an attempt to avoid the overhead of synchronization.
- For example, the <code>twoprint</code> program might be
- incorrectly written as:
- </p>
- <pre>
- var a string
- var done bool
- func setup() {
- a = "hello, world"
- done = true
- }
- func doprint() {
- if !done {
- once.Do(setup)
- }
- print(a)
- }
- func twoprint() {
- go doprint()
- go doprint()
- }
- </pre>
- <p>
- but there is no guarantee that, in <code>doprint</code>, observing the write to <code>done</code>
- implies observing the write to <code>a</code>. This
- version can (incorrectly) print an empty string
- instead of <code>"hello, world"</code>.
- </p>
- <p>
- Another incorrect idiom is busy waiting for a value, as in:
- </p>
- <pre>
- var a string
- var done bool
- func setup() {
- a = "hello, world"
- done = true
- }
- func main() {
- go setup()
- for !done {
- }
- print(a)
- }
- </pre>
- <p>
- As before, there is no guarantee that, in <code>main</code>,
- observing the write to <code>done</code>
- implies observing the write to <code>a</code>, so this program could
- print an empty string too.
- Worse, there is no guarantee that the write to <code>done</code> will ever
- be observed by <code>main</code>, since there are no synchronization
- events between the two threads. The loop in <code>main</code> is not
- guaranteed to finish.
- </p>
- <p>
- There are subtler variants on this theme, such as this program.
- </p>
- <pre>
- type T struct {
- msg string
- }
- var g *T
- func setup() {
- t := new(T)
- t.msg = "hello, world"
- g = t
- }
- func main() {
- go setup()
- for g == nil {
- }
- print(g.msg)
- }
- </pre>
- <p>
- Even if <code>main</code> observes <code>g != nil</code> and exits its loop,
- there is no guarantee that it will observe the initialized
- value for <code>g.msg</code>.
- </p>
- <p>
- In all these examples, the solution is the same:
- use explicit synchronization.
- </p>
|