doc/go_mem.html HTML 978 lines View on github.com → Search inside
1<!--{2	"Title": "The Go Memory Model",3	"Subtitle": "Version of June 6, 2022",4	"Path": "/ref/mem"5}-->67<style>8p.rule {9  font-style: italic;10}11</style>1213<h2 id="introduction">Introduction</h2>1415<p>16The Go memory model specifies the conditions under which17reads of a variable in one goroutine can be guaranteed to18observe values produced by writes to the same variable in a different goroutine.19</p>202122<h3 id="advice">Advice</h3>2324<p>25Programs that modify data being simultaneously accessed by multiple goroutines26must serialize such access.27</p>2829<p>30To serialize access, protect the data with channel operations or other synchronization primitives31such as those in the <a href="/pkg/sync/"><code>sync</code></a>32and <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> packages.33</p>3435<p>36If you must read the rest of this document to understand the behavior of your program,37you are being too clever.38</p>3940<p>41Don't be clever.42</p>4344<h3 id="overview">Informal Overview</h3>4546<p>47Go approaches its memory model in much the same way as the rest of the language,48aiming to keep the semantics simple, understandable, and useful.49This section gives a general overview of the approach and should suffice for most programmers.50The memory model is specified more formally in the next section.51</p>5253<p>54A <em>data race</em> is defined as55a write to a memory location happening concurrently with another read or write to that same location,56unless all the accesses involved are atomic data accesses as provided by the <code>sync/atomic</code> package.57As noted already, programmers are strongly encouraged to use appropriate synchronization58to avoid data races.59In the absence of data races, Go programs behave as if all the goroutines60were multiplexed onto a single processor.61This property is sometimes referred to as DRF-SC: data-race-free programs62execute in a sequentially consistent manner.63</p>6465<p>66While programmers should write Go programs without data races,67there are limitations to what a Go implementation can do in response to a data race.68An implementation may always react to a data race by reporting the race and terminating the program.69Otherwise, each read of a single-word-sized or sub-word-sized memory location70must observe a value actually written to that location (perhaps by a concurrent executing goroutine)71and not yet overwritten.72These implementation constraints make Go more like Java or JavaScript,73in that most races have a limited number of outcomes,74and less like C and C++, where the meaning of any program with a race75is entirely undefined, and the compiler may do anything at all.76Go's approach aims to make errant programs more reliable and easier to debug,77while still insisting that races are errors and that tools can diagnose and report them.78</p>7980<h2 id="model">Memory Model</h2>8182<p>83The following formal definition of Go's memory model closely follows84the approach presented by Hans-J. Boehm and Sarita V. Adve in85“<a href="https://dl.acm.org/doi/10.1145/1375581.1375591">Foundations of the C++ Concurrency Memory Model</a>”,86published in PLDI 2008.87The definition of data-race-free programs and the guarantee of sequential consistency88for race-free programs are equivalent to the ones in that work.89</p>9091<p>92The memory model describes the requirements on program executions,93which are made up of goroutine executions,94which in turn are made up of memory operations.95</p>9697<p>98A <i>memory operation</i> is modeled by four details:99</p>100<ul>101	<li>its kind, indicating whether it is an ordinary data read, an ordinary data write,102    or a <i>synchronizing operation</i> such as an atomic data access,103	a mutex operation, or a channel operation,</li>104	<li>its location in the program,</li>105	<li>the memory location or variable being accessed, and</li>106	<li>the values read or written by the operation.</li>107</ul>108<p>109Some memory operations are <i>read-like</i>, including read, atomic read, mutex lock, and channel receive.110Other memory operations are <i>write-like</i>, including write, atomic write, mutex unlock, channel send, and channel close.111Some, such as atomic compare-and-swap, are both read-like and write-like.112</p>113114<p>115A <i>goroutine execution</i> is modeled as a set of memory operations executed by a single goroutine.116</p>117118<p>119<b>Requirement 1</b>:120The memory operations in each goroutine must correspond to a correct sequential execution of that goroutine,121given the values read from and written to memory.122That execution must be consistent with the <i>sequenced before</i> relation,123defined as the partial order requirements set out by the <a href="/ref/spec">Go language specification</a>124for Go's control flow constructs as well as the <a href="/ref/spec#Order_of_evaluation">order of evaluation for expressions</a>.125</p>126127<p>128A Go <i>program execution</i> is modeled as a set of goroutine executions,129together with a mapping <i>W</i> that specifies the write-like operation that each read-like operation reads from.130(Multiple executions of the same program can have different program executions.)131</p>132133<p>134<b>Requirement 2</b>:135For a given program execution, the mapping <i>W</i>, when limited to synchronizing operations,136must be explainable by some implicit total order of the synchronizing operations137that is consistent with sequencing and the values read and written by those operations.138</p>139140<p>141The <i>synchronized before</i> relation is a partial order on synchronizing memory operations,142derived from <i>W</i>.143If a synchronizing read-like memory operation <i>r</i>144observes a synchronizing write-like memory operation <i>w</i>145(that is, if <i>W</i>(<i>r</i>) = <i>w</i>),146then <i>w</i> is synchronized before <i>r</i>.147Informally, the synchronized before relation is a subset of the implied total order148mentioned in the previous paragraph,149limited to the information that <i>W</i> directly observes.150</p>151152<p>153The <i>happens before</i> relation is defined as the transitive closure of the154union of the sequenced before and synchronized before relations.155</p>156157<p>158<b>Requirement 3</b>:159For an ordinary (non-synchronizing) data read <i>r</i> on a memory location <i>x</i>,160<i>W</i>(<i>r</i>) must be a write <i>w</i> that is <i>visible</i> to <i>r</i>,161where visible means that both of the following hold:162</p>163164<ol>165	<li><i>w</i> happens before <i>r</i>.</li>166	<li><i>w</i> does not happen before any other write <i>w'</i> (to <i>x</i>) that happens before <i>r</i>.</li>167</ol>168169<p>170A <i>read-write data race</i> on memory location <i>x</i>171consists of a read-like memory operation <i>r</i> on <i>x</i>172and a write-like memory operation <i>w</i> on <i>x</i>,173at least one of which is non-synchronizing,174which are unordered by happens before175(that is, neither <i>r</i> happens before <i>w</i>176nor <i>w</i> happens before <i>r</i>).177</p>178179<p>180A <i>write-write data race</i> on memory location <i>x</i>181consists of two write-like memory operations <i>w</i> and <i>w'</i> on <i>x</i>,182at least one of which is non-synchronizing,183which are unordered by happens before.184</p>185186<p>187Note that if there are no read-write or write-write data races on memory location <i>x</i>,188then any read <i>r</i> on <i>x</i> has only one possible <i>W</i>(<i>r</i>):189the single <i>w</i> that immediately precedes it in the happens before order.190</p>191192<p>193More generally, it can be shown that any Go program that is data-race-free,194meaning it has no program executions with read-write or write-write data races,195can only have outcomes explained by some sequentially consistent interleaving196of the goroutine executions.197(The proof is the same as Section 7 of Boehm and Adve's paper cited above.)198This property is called DRF-SC.199</p>200201<p>202The intent of the formal definition is to match203the DRF-SC guarantee provided to race-free programs204by other languages, including C, C++, Java, JavaScript, Rust, and Swift.205</p>206207<p>208Certain Go language operations such as goroutine creation and memory allocation209act as synchronization operations.210The effect of these operations on the synchronized-before partial order211is documented in the Synchronization section below.212Individual packages are responsible for providing similar documentation213for their own operations.214</p>215216<h2 id="restrictions">Implementation Restrictions for Programs Containing Data Races</h2>217218<p>219The preceding section gave a formal definition of data-race-free program execution.220This section informally describes the semantics that implementations must provide221for programs that do contain races.222</p>223224<p>225Any implementation can, upon detecting a data race,226report the race and halt execution of the program.227Implementations using ThreadSanitizer228(accessed with “<code>go</code> <code>build</code> <code>-race</code>”)229do exactly this.230</p>231232<p>233A read of an array, struct, or complex number234may be implemented as a read of each individual sub-value235(array element, struct field, or real/imaginary component),236in any order.237Similarly, a write of an array, struct, or complex number238may be implemented as a write of each individual sub-value,239in any order.240</p>241242<p>243A read <i>r</i> of a memory location <i>x</i>244holding a value245that is not larger than a machine word must observe246some write <i>w</i> such that <i>r</i> does not happen before <i>w</i>247and there is no write <i>w'</i> such that <i>w</i> happens before <i>w'</i>248and <i>w'</i> happens before <i>r</i>.249That is, each read must observe a value written by a preceding or concurrent write.250</p>251252<p>253Additionally, observation of acausal and out of thin air writes is disallowed.254</p>255256<p>257Reads of memory locations larger than a single machine word258are encouraged but not required to meet the same semantics259as word-sized memory locations,260observing a single allowed write <i>w</i>.261For performance reasons,262implementations may instead treat larger operations263as a set of individual machine-word-sized operations264in an unspecified order.265This means that races on multiword data structures266can lead to inconsistent values not corresponding to a single write.267When the values depend on the consistency268of internal (pointer, length) or (pointer, type) pairs,269as can be the case for interface values, maps,270slices, and strings in most Go implementations,271such races can in turn lead to arbitrary memory corruption.272</p>273274<p>275Examples of incorrect synchronization are given in the276Incorrect synchronization section below.277</p>278279<p>280Examples of the limitations on implementations are given in the281Incorrect compilation section below.282</p>283284<h2 id="synchronization">Synchronization</h2>285286<h3 id="init">Initialization</h3>287288<p>289Program initialization runs in a single goroutine,290but that goroutine may create other goroutines,291which run concurrently.292</p>293294<p class="rule">295If a package <code>p</code> imports package <code>q</code>, the completion of296<code>q</code>'s <code>init</code> functions happens before the start of any of <code>p</code>'s.297</p>298299<p class="rule">300The completion of all <code>init</code> functions is synchronized before301the start of the function <code>main.main</code>.302</p>303304<h3 id="go">Goroutine creation</h3>305306<p class="rule">307The <code>go</code> statement that starts a new goroutine308is synchronized before the start of the goroutine's execution.309</p>310311<p>312For example, in this program:313</p>314315<pre>316var a string317318func f() {319	print(a)320}321322func hello() {323	a = "hello, world"324	go f()325}326</pre>327328<p>329calling <code>hello</code> will print <code>"hello, world"</code>330at some point in the future (perhaps after <code>hello</code> has returned).331</p>332333<h3 id="goexit">Goroutine destruction</h3>334335<p>336The exit of a goroutine is not guaranteed to be synchronized before337any event in the program.338For example, in this program:339</p>340341<pre>342var a string343344func hello() {345	go func() { a = "hello" }()346	print(a)347}348</pre>349350<p>351the assignment to <code>a</code> is not followed by352any synchronization event, so it is not guaranteed to be353observed by any other goroutine.354In fact, an aggressive compiler might delete the entire <code>go</code> statement.355</p>356357<p>358If the effects of a goroutine must be observed by another goroutine,359use a synchronization mechanism such as a lock or channel360communication to establish a relative ordering.361</p>362363<h3 id="chan">Channel communication</h3>364365<p>366Channel communication is the main method of synchronization367between goroutines.  Each send on a particular channel368is matched to a corresponding receive from that channel,369usually in a different goroutine.370</p>371372<p class="rule">373A send on a channel is synchronized before the completion of the374corresponding receive from that channel.375</p>376377<p>378This program:379</p>380381<pre>382var c = make(chan int, 10)383var a string384385func f() {386	a = "hello, world"387	c &lt;- 0388}389390func main() {391	go f()392	&lt;-c393	print(a)394}395</pre>396397<p>398is guaranteed to print <code>"hello, world"</code>.  The write to <code>a</code>399is sequenced before the send on <code>c</code>, which is synchronized before400the corresponding receive on <code>c</code> completes, which is sequenced before401the <code>print</code>.402</p>403404<p class="rule">405The closing of a channel is synchronized before a receive that returns a zero value406because the channel is closed.407</p>408409<p>410In the previous example, replacing411<code>c &lt;- 0</code> with <code>close(c)</code>412yields a program with the same guaranteed behavior.413</p>414415<p class="rule">416A receive from an unbuffered channel is synchronized before the completion of417the corresponding send on that channel.418</p>419420<p>421This program (as above, but with the send and receive statements swapped and422using an unbuffered channel):423</p>424425<pre>426var c = make(chan int)427var a string428429func f() {430	a = "hello, world"431	&lt;-c432}433434func main() {435	go f()436	c &lt;- 0437	print(a)438}439</pre>440441<p>442is also guaranteed to print <code>"hello, world"</code>.  The write to <code>a</code>443is sequenced before the receive on <code>c</code>, which is synchronized before444the corresponding send on <code>c</code> completes, which is sequenced445before the <code>print</code>.446</p>447448<p>449If the channel were buffered (e.g., <code>c = make(chan int, 1)</code>)450then the program would not be guaranteed to print451<code>"hello, world"</code>.  (It might print the empty string,452crash, or do something else.)453</p>454455<p class="rule">456The <i>k</i>th receive from a channel with capacity <i>C</i> is synchronized before the completion of the <i>k</i>+<i>C</i>th send on that channel.457</p>458459<p>460This rule generalizes the previous rule to buffered channels.461It allows a counting semaphore to be modeled by a buffered channel:462the number of items in the channel corresponds to the number of active uses,463the capacity of the channel corresponds to the maximum number of simultaneous uses,464sending an item acquires the semaphore, and receiving an item releases465the semaphore.466This is a common idiom for limiting concurrency.467</p>468469<p>470This program starts a goroutine for every entry in the work list, but the471goroutines coordinate using the <code>limit</code> channel to ensure472that at most three are running work functions at a time.473</p>474475<pre>476var limit = make(chan int, 3)477478func main() {479	for _, w := range work {480		go func(w func()) {481			limit &lt;- 1482			w()483			&lt;-limit484		}(w)485	}486	select{}487}488</pre>489490<h3 id="locks">Locks</h3>491492<p>493The <code>sync</code> package implements two lock data types,494<code>sync.Mutex</code> and <code>sync.RWMutex</code>.495</p>496497<p class="rule">498For any <code>sync.Mutex</code> or <code>sync.RWMutex</code> variable <code>l</code> and <i>n</i> &lt; <i>m</i>,499call <i>n</i> of <code>l.Unlock()</code> is synchronized before call <i>m</i> of <code>l.Lock()</code> returns.500</p>501502<p>503This program:504</p>505506<pre>507var l sync.Mutex508var a string509510func f() {511	a = "hello, world"512	l.Unlock()513}514515func main() {516	l.Lock()517	go f()518	l.Lock()519	print(a)520}521</pre>522523<p>524is guaranteed to print <code>"hello, world"</code>.525The first call to <code>l.Unlock()</code> (in <code>f</code>) is synchronized526before the second call to <code>l.Lock()</code> (in <code>main</code>) returns,527which is sequenced before the <code>print</code>.528</p>529530<p class="rule">531For any call to <code>l.RLock</code> on a <code>sync.RWMutex</code> variable <code>l</code>,532there is an <i>n</i> such that the <i>n</i>th call to <code>l.Unlock</code>533is synchronized before the return from <code>l.RLock</code>,534and the matching call to <code>l.RUnlock</code> is synchronized before the return from call <i>n</i>+1 to <code>l.Lock</code>.535</p>536537<p class="rule">538A successful call to <code>l.TryLock</code> (or <code>l.TryRLock</code>)539is equivalent to a call to <code>l.Lock</code> (or <code>l.RLock</code>).540An unsuccessful call has no synchronizing effect at all.541As far as the memory model is concerned,542<code>l.TryLock</code> (or <code>l.TryRLock</code>)543may be considered to be able to return false544even when the mutex <i>l</i> is unlocked.545</p>546547<h3 id="once">Once</h3>548549<p>550The <code>sync</code> package provides a safe mechanism for551initialization in the presence of multiple goroutines552through the use of the <code>Once</code> type.553Multiple threads can execute <code>once.Do(f)</code> for a particular <code>f</code>,554but only one will run <code>f()</code>, and the other calls block555until <code>f()</code> has returned.556</p>557558<p class="rule">559The completion of a single call of <code>f()</code> from <code>once.Do(f)</code>560is synchronized before the return of any call of <code>once.Do(f)</code>.561</p>562563<p>564In this program:565</p>566567<pre>568var a string569var once sync.Once570571func setup() {572	a = "hello, world"573}574575func doprint() {576	once.Do(setup)577	print(a)578}579580func twoprint() {581	go doprint()582	go doprint()583}584</pre>585586<p>587calling <code>twoprint</code> will call <code>setup</code> exactly588once.589The <code>setup</code> function will complete before either call590of <code>print</code>.591The result will be that <code>"hello, world"</code> will be printed592twice.593</p>594595<h3 id="atomic">Atomic Values</h3>596597<p>598The APIs in the <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a>599package are collectively atomic operations600that can be used to synchronize the execution of different goroutines.601If the effect of an atomic operation <i>A</i> is observed by atomic operation <i>B</i>,602then <i>A</i> is synchronized before <i>B</i>.603All the atomic operations executed in a program behave as though executed604in some sequentially consistent order.605</p>606607<p>608The preceding definition has the same semantics as C++’s sequentially consistent atomics609and Javas <code>volatile</code> variables.610</p>611612<h3 id="finalizer">Finalizers</h3>613614<p>615The <a href="/pkg/runtime/"><code>runtime</code></a> package provides616a <code>SetFinalizer</code> function that adds a finalizer to be called when617a particular object is no longer reachable by the program.618A call to <code>SetFinalizer(x, f)</code> is synchronized before the finalization call <code>f(x)</code>.619</p>620621<h3 id="more">Additional Mechanisms</h3>622623<p>624The <code>sync</code> package provides additional synchronization abstractions,625including <a href="/pkg/sync/#Cond">condition variables</a>,626<a href="/pkg/sync/#Map">lock-free maps</a>,627<a href="/pkg/sync/#Pool">allocation pools</a>,628and629<a href="/pkg/sync/#WaitGroup">wait groups</a>.630The documentation for each of these specifies the guarantees it631makes concerning synchronization.632</p>633634<p>635Other packages that provide synchronization abstractions636should document the guarantees they make too.637</p>638639640<h2 id="badsync">Incorrect synchronization</h2>641642<p>643Programs with races are incorrect and644can exhibit non-sequentially consistent executions.645In particular, note that a read <i>r</i> may observe the value written by any write <i>w</i>646that executes concurrently with <i>r</i>.647Even if this occurs, it does not imply that reads happening after <i>r</i>648will observe writes that happened before <i>w</i>.649</p>650651<p>652In this program:653</p>654655<pre>656var a, b int657658func f() {659	a = 1660	b = 2661}662663func g() {664	print(b)665	print(a)666}667668func main() {669	go f()670	g()671}672</pre>673674<p>675it can happen that <code>g</code> prints <code>2</code> and then <code>0</code>.676</p>677678<p>679This fact invalidates a few common idioms.680</p>681682<p>683Double-checked locking is an attempt to avoid the overhead of synchronization.684For example, the <code>twoprint</code> program might be685incorrectly written as:686</p>687688<pre>689var a string690var done bool691692func setup() {693	a = "hello, world"694	done = true695}696697func doprint() {698	if !done {699		once.Do(setup)700	}701	print(a)702}703704func twoprint() {705	go doprint()706	go doprint()707}708</pre>709710<p>711but there is no guarantee that, in <code>doprint</code>, observing the write to <code>done</code>712implies observing the write to <code>a</code>.  This713version can (incorrectly) print an empty string714instead of <code>"hello, world"</code>.715</p>716717<p>718Another incorrect idiom is busy waiting for a value, as in:719</p>720721<pre>722var a string723var done bool724725func setup() {726	a = "hello, world"727	done = true728}729730func main() {731	go setup()732	for !done {733	}734	print(a)735}736</pre>737738<p>739As before, there is no guarantee that, in <code>main</code>,740observing the write to <code>done</code>741implies observing the write to <code>a</code>, so this program could742print an empty string too.743Worse, there is no guarantee that the write to <code>done</code> will ever744be observed by <code>main</code>, since there are no synchronization745events between the two threads.  The loop in <code>main</code> is not746guaranteed to finish.747</p>748749<p>750There are subtler variants on this theme, such as this program.751</p>752753<pre>754type T struct {755	msg string756}757758var g *T759760func setup() {761	t := new(T)762	t.msg = "hello, world"763	g = t764}765766func main() {767	go setup()768	for g == nil {769	}770	print(g.msg)771}772</pre>773774<p>775Even if <code>main</code> observes <code>g != nil</code> and exits its loop,776there is no guarantee that it will observe the initialized777value for <code>g.msg</code>.778</p>779780<p>781In all these examples, the solution is the same:782use explicit synchronization.783</p>784785<h2 id="badcompiler">Incorrect compilation</h2>786787<p>788The Go memory model restricts compiler optimizations as much as it does Go programs.789Some compiler optimizations that would be valid in single-threaded programs are not valid in all Go programs.790In particular, a compiler must not introduce writes that do not exist in the original program,791it must not allow a single read to observe multiple values,792and it must not allow a single write to write multiple values.793</p>794795<p>796All the following examples assume that `*p` and `*q` refer to797memory locations accessible to multiple goroutines.798</p>799800<p>801Not introducing data races into race-free programs means not moving802writes out of conditional statements in which they appear.803For example, a compiler must not invert the conditional in this program:804</p>805806<pre>807*p = 1808if cond {809	*p = 2810}811</pre>812813<p>814That is, the compiler must not rewrite the program into this one:815</p>816817<pre>818*p = 2819if !cond {820	*p = 1821}822</pre>823824<p>825If <code>cond</code> is false and another goroutine is reading <code>*p</code>,826then in the original program, the other goroutine can only observe any prior value of <code>*p</code> and <code>1</code>.827In the rewritten program, the other goroutine can observe <code>2</code>, which was previously impossible.828</p>829830<p>831Not introducing data races also means not assuming that loops terminate.832For example, a compiler must in general not move the accesses to <code>*p</code> or <code>*q</code>833ahead of the loop in this program:834</p>835836<pre>837n := 0838for e := list; e != nil; e = e.next {839	n++840}841i := *p842*q = 1843</pre>844845<p>846If <code>list</code> pointed to a cyclic list,847then the original program would never access <code>*p</code> or <code>*q</code>,848but the rewritten program would.849(Moving `*p` ahead would be safe if the compiler can prove `*p` will not panic;850moving `*q` ahead would also require the compiler proving that no other851goroutine can access `*q`.)852</p>853854<p>855Not introducing data races also means not assuming that called functions856always return or are free of synchronization operations.857For example, a compiler must not move the accesses to <code>*p</code> or <code>*q</code>858ahead of the function call in this program859(at least not without direct knowledge of the precise behavior of <code>f</code>):860</p>861862<pre>863f()864i := *p865*q = 1866</pre>867868<p>869If the call never returned, then once again the original program870would never access <code>*p</code> or <code>*q</code>, but the rewritten program would.871And if the call contained synchronizing operations, then the original program872could establish happens before edges preceding the accesses873to <code>*p</code> and <code>*q</code>, but the rewritten program would not.874</p>875876<p>877Not allowing a single read to observe multiple values means878not reloading local variables from shared memory.879For example, a compiler must not discard <code>i</code> and reload it880a second time from <code>*p</code> in this program:881</p>882883<pre>884i := *p885if i &lt; 0 || i &gt;= len(funcs) {886	panic("invalid function index")887}888... complex code ...889// compiler must NOT reload i = *p here890funcs[i]()891</pre>892893<p>894If the complex code needs many registers, a compiler for single-threaded programs895could discard <code>i</code> without saving a copy and then reload896<code>i = *p</code> just before897<code>funcs[i]()</code>.898A Go compiler must not, because the value of <code>*p</code> may have changed.899(Instead, the compiler could spill <code>i</code> to the stack.)900</p>901902<p>903Not allowing a single write to write multiple values also means not using904the memory where a local variable will be written as temporary storage before the write.905For example, a compiler must not use <code>*p</code> as temporary storage in this program:906</p>907908<pre>909*p = i + *p/2910</pre>911912<p>913That is, it must not rewrite the program into this one:914</p>915916<pre>917*p /= 2918*p += i919</pre>920921<p>922If <code>i</code> and <code>*p</code> start equal to 2,923the original code does <code>*p = 3</code>,924so a racing thread can read only 2 or 3 from <code>*p</code>.925The rewritten code does <code>*p = 1</code> and then <code>*p = 3</code>,926allowing a racing thread to read 1 as well.927</p>928929<p>930Note that all these optimizations are permitted in C/C++ compilers:931a Go compiler sharing a back end with a C/C++ compiler must take care932to disable optimizations that are invalid for Go.933</p>934935<p>936Note that the prohibition on introducing data races937does not apply if the compiler can prove that the races938do not affect correct execution on the target platform.939For example, on essentially all CPUs, it is valid to rewrite940</p>941942<pre>943n := 0944for i := 0; i < m; i++ {945	n += *shared946}947</pre>948949into:950951<pre>952n := 0953local := *shared954for i := 0; i < m; i++ {955	n += local956}957</pre>958959<p>960provided it can be proved that <code>*shared</code> will not fault on access,961because the potential added read will not affect any existing concurrent reads or writes.962On the other hand, the rewrite would not be valid in a source-to-source translator.963</p>964965<h2 id="conclusion">Conclusion</h2>966967<p>968Go programmers writing data-race-free programs can rely on969sequentially consistent execution of those programs,970just as in essentially all other modern programming languages.971</p>972973<p>974When it comes to programs with races,975both programmers and compilers should remember the advice:976don't be clever.977</p>

Code quality findings 1

Inline CSS detected; use external stylesheets for maintainability and performance
info maintainability inline-css
<style>

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.