aboutsummaryrefslogtreecommitdiff
path: root/doc/go_mem.html
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2009-03-22 21:53:40 -0700
committerRob Pike <r@golang.org>2009-03-22 21:53:40 -0700
commit482cbb1f3358bd5d106d1de25f7080080532f8a6 (patch)
tree239f8d27360fcd84b05fd20c6aa6b3df52d7417c /doc/go_mem.html
parent7525e085d26d85a3f104f9abdcf3a47e937aa0ff (diff)
downloadgo-482cbb1f3358bd5d106d1de25f7080080532f8a6.tar.gz
go-482cbb1f3358bd5d106d1de25f7080080532f8a6.zip
change file name so it can be copied without name change to a more public place.
R=rsc DELTA=1090 (545 added, 545 deleted, 0 changed) OCL=26629 CL=26629
Diffstat (limited to 'doc/go_mem.html')
-rw-r--r--doc/go_mem.html458
1 files changed, 458 insertions, 0 deletions
diff --git a/doc/go_mem.html b/doc/go_mem.html
new file mode 100644
index 0000000000..5228196d2c
--- /dev/null
+++ b/doc/go_mem.html
@@ -0,0 +1,458 @@
+
+<h1>The Go memory model</h1>
+
+<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>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 execution behavior within that goroutine.
+Because of this reordering, the execution order observed
+by one may differ from the order perceived
+by another. For example, if one goroutine
+executes <code>a = 1; b = 2;</code>, a second goroutine might observe
+the updated value of <code>b</code> before the updated value of <code>a</code>.
+</p>
+
+<p>
+To specify the requirements on 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>
+Within a single goroutine, the happens before order is the
+order specified 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">w</span> happens before <span class="event">r</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, and
+new goroutines created during initialization do not
+start running until initialization ends.
+</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>
+
+<p class="rule">
+The execution of any goroutines created during <code>init</code>
+functions 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>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>
+For example, this program:
+</p>
+
+<pre>
+var c = make(chan int, 10);
+var a string;
+
+func f() {
+ a = "hello, world";
+ c &lt;- 0;
+}
+
+func main() {
+ go f();
+ &lt;-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">
+A receive from an unbuffered channel happens before
+the send on that channel completes.
+</p>
+
+<p>
+For example, this program:
+</p>
+
+<pre>
+var c = make(chan int);
+var a string;
+
+func f() {
+ a = "hello, world";
+ &lt;-c;
+}
+</pre>
+
+<pre>
+func main() {
+ go f();
+ c &lt;- 0;
+ print(a);
+}
+</pre>
+
+<p>
+is also guaranteed to print "hello, world". 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;
+it cannot print <code>"hello, sailor"</code>, nor can it crash.)
+</p>
+
+<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> variable <code>l</code> and <i>n</i> &lt; <i>m</i>,
+the <i>n</i>'th call to <code>l.Unlock()</code> happens before the <i>m</i>'th call to <code>l.Lock()</code> returns.
+</p>
+
+<p>
+For example, 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>
+TODO(rsc): <code>sync.RWMutex</code>.
+</p>
+
+<h3>Once</h3>
+
+<p>
+The <code>once</code> package provides a safe mechanism for
+initialization in the presence of multiple goroutines.
+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>
+A single call to <code>f()</code> happens before <code>once.Do(f)</code> returns.
+</p>
+
+<p>
+For example, in this program:
+</p>
+
+<pre>
+var a string;
+
+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>twoprint</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>
+For example, 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 obvious idioms.
+</p>
+
+<p>
+Double-checked locking is an attempt to avoid the overhead of synchronization.
+For example, the <code>twoprint</code> program above, 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 of 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. For example, in 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>
+
+</body>
+</html>
+