OLD | NEW |
1 <!-- The Go Memory Model --> | 1 <!-- The Go Memory Model --> |
2 | 2 |
3 <h2>Introduction</h2> | 3 <h2>Introduction</h2> |
4 | 4 |
5 <p> | 5 <p> |
6 The Go memory model specifies the conditions under which | 6 The Go memory model specifies the conditions under which |
7 reads of a variable in one goroutine can be guaranteed to | 7 reads of a variable in one goroutine can be guaranteed to |
8 observe values produced by writes to the same variable in a different goroutine. | 8 observe values produced by writes to the same variable in a different goroutine. |
9 </p> | 9 </p> |
10 | 10 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 <p class="rule"> | 119 <p class="rule"> |
120 The <code>go</code> statement that starts a new goroutine | 120 The <code>go</code> statement that starts a new goroutine |
121 happens before the goroutine's execution begins. | 121 happens before the goroutine's execution begins. |
122 </p> | 122 </p> |
123 | 123 |
124 <p> | 124 <p> |
125 For example, in this program: | 125 For example, in this program: |
126 </p> | 126 </p> |
127 | 127 |
128 <pre> | 128 <pre> |
129 var a string; | 129 var a string |
130 | 130 |
131 func f() { | 131 func f() { |
132 » print(a); | 132 » print(a) |
133 } | 133 } |
134 | 134 |
135 func hello() { | 135 func hello() { |
136 » a = "hello, world"; | 136 » a = "hello, world" |
137 » go f(); | 137 » go f() |
138 } | 138 } |
139 </pre> | 139 </pre> |
140 | 140 |
141 <p> | 141 <p> |
142 calling <code>hello</code> will print <code>"hello, world"</code> | 142 calling <code>hello</code> will print <code>"hello, world"</code> |
143 at some point in the future (perhaps after <code>hello</code> has returned). | 143 at some point in the future (perhaps after <code>hello</code> has returned). |
144 </p> | 144 </p> |
145 | 145 |
146 <h3>Channel communication</h3> | 146 <h3>Channel communication</h3> |
147 | 147 |
(...skipping 11 matching lines...) Expand all Loading... |
159 | 159 |
160 <p> | 160 <p> |
161 This program: | 161 This program: |
162 </p> | 162 </p> |
163 | 163 |
164 <pre> | 164 <pre> |
165 var c = make(chan int, 10) | 165 var c = make(chan int, 10) |
166 var a string | 166 var a string |
167 | 167 |
168 func f() { | 168 func f() { |
169 » a = "hello, world"; | 169 » a = "hello, world" |
170 » c <- 0; | 170 » c <- 0 |
171 } | 171 } |
172 | 172 |
173 func main() { | 173 func main() { |
174 » go f(); | 174 » go f() |
175 » <-c; | 175 » <-c |
176 » print(a); | 176 » print(a) |
177 } | 177 } |
178 </pre> | 178 </pre> |
179 | 179 |
180 <p> | 180 <p> |
181 is guaranteed to print <code>"hello, world"</code>. The write to <code>a</code> | 181 is guaranteed to print <code>"hello, world"</code>. The write to <code>a</code> |
182 happens before the send on <code>c</code>, which happens before | 182 happens before the send on <code>c</code>, which happens before |
183 the corresponding receive on <code>c</code> completes, which happens before | 183 the corresponding receive on <code>c</code> completes, which happens before |
184 the <code>print</code>. | 184 the <code>print</code>. |
185 </p> | 185 </p> |
186 | 186 |
187 <p class="rule"> | 187 <p class="rule"> |
188 A receive from an unbuffered channel happens before | 188 A receive from an unbuffered channel happens before |
189 the send on that channel completes. | 189 the send on that channel completes. |
190 </p> | 190 </p> |
191 | 191 |
192 <p> | 192 <p> |
193 This program (as above, but with the send and receive statements swapped and | 193 This program (as above, but with the send and receive statements swapped and |
194 using an unbuffered channel): | 194 using an unbuffered channel): |
195 </p> | 195 </p> |
196 | 196 |
197 <pre> | 197 <pre> |
198 var c = make(chan int) | 198 var c = make(chan int) |
199 var a string | 199 var a string |
200 | 200 |
201 func f() { | 201 func f() { |
202 » a = "hello, world"; | 202 » a = "hello, world" |
203 » <-c; | 203 » <-c |
204 } | 204 } |
205 </pre> | 205 </pre> |
206 | 206 |
207 <pre> | 207 <pre> |
208 func main() { | 208 func main() { |
209 » go f(); | 209 » go f() |
210 » c <- 0; | 210 » c <- 0 |
211 » print(a); | 211 » print(a) |
212 } | 212 } |
213 </pre> | 213 </pre> |
214 | 214 |
215 <p> | 215 <p> |
216 is also guaranteed to print <code>"hello, world"</code>. The write to <code>a</
code> | 216 is also guaranteed to print <code>"hello, world"</code>. The write to <code>a</
code> |
217 happens before the receive on <code>c</code>, which happens before | 217 happens before the receive on <code>c</code>, which happens before |
218 the corresponding send on <code>c</code> completes, which happens | 218 the corresponding send on <code>c</code> completes, which happens |
219 before the <code>print</code>. | 219 before the <code>print</code>. |
220 </p> | 220 </p> |
221 | 221 |
(...skipping 18 matching lines...) Expand all Loading... |
240 | 240 |
241 <p> | 241 <p> |
242 This program: | 242 This program: |
243 </p> | 243 </p> |
244 | 244 |
245 <pre> | 245 <pre> |
246 var l sync.Mutex | 246 var l sync.Mutex |
247 var a string | 247 var a string |
248 | 248 |
249 func f() { | 249 func f() { |
250 » a = "hello, world"; | 250 » a = "hello, world" |
251 » l.Unlock(); | 251 » l.Unlock() |
252 } | 252 } |
253 | 253 |
254 func main() { | 254 func main() { |
255 » l.Lock(); | 255 » l.Lock() |
256 » go f(); | 256 » go f() |
257 » l.Lock(); | 257 » l.Lock() |
258 » print(a); | 258 » print(a) |
259 } | 259 } |
260 </pre> | 260 </pre> |
261 | 261 |
262 <p> | 262 <p> |
263 is guaranteed to print <code>"hello, world"</code>. | 263 is guaranteed to print <code>"hello, world"</code>. |
264 The first call to <code>l.Unlock()</code> (in <code>f</code>) happens | 264 The first call to <code>l.Unlock()</code> (in <code>f</code>) happens |
265 before the second call to <code>l.Lock()</code> (in <code>main</code>) returns, | 265 before the second call to <code>l.Lock()</code> (in <code>main</code>) returns, |
266 which happens before the <code>print</code>. | 266 which happens before the <code>print</code>. |
267 </p> | 267 </p> |
268 | 268 |
(...skipping 19 matching lines...) Expand all Loading... |
288 </p> | 288 </p> |
289 | 289 |
290 <p> | 290 <p> |
291 In this program: | 291 In this program: |
292 </p> | 292 </p> |
293 | 293 |
294 <pre> | 294 <pre> |
295 var a string | 295 var a string |
296 | 296 |
297 func setup() { | 297 func setup() { |
298 » a = "hello, world"; | 298 » a = "hello, world" |
299 } | 299 } |
300 | 300 |
301 func doprint() { | 301 func doprint() { |
302 » once.Do(setup); | 302 » once.Do(setup) |
303 » print(a); | 303 » print(a) |
304 } | 304 } |
305 | 305 |
306 func twoprint() { | 306 func twoprint() { |
307 » go doprint(); | 307 » go doprint() |
308 » go doprint(); | 308 » go doprint() |
309 } | 309 } |
310 </pre> | 310 </pre> |
311 | 311 |
312 <p> | 312 <p> |
313 calling <code>twoprint</code> causes <code>"hello, world"</code> to be printed t
wice. | 313 calling <code>twoprint</code> causes <code>"hello, world"</code> to be printed t
wice. |
314 The first call to <code>twoprint</code> runs <code>setup</code> once. | 314 The first call to <code>twoprint</code> runs <code>setup</code> once. |
315 </p> | 315 </p> |
316 | 316 |
317 <h2>Incorrect synchronization</h2> | 317 <h2>Incorrect synchronization</h2> |
318 | 318 |
319 <p> | 319 <p> |
320 Note that a read <span class="event">r</span> may observe the value written by a
write <span class="event">w</span> | 320 Note that a read <span class="event">r</span> may observe the value written by a
write <span class="event">w</span> |
321 that happens concurrently with <span class="event">r</span>. | 321 that happens concurrently with <span class="event">r</span>. |
322 Even if this occurs, it does not imply that reads happening after <span class="e
vent">r</span> | 322 Even if this occurs, it does not imply that reads happening after <span class="e
vent">r</span> |
323 will observe writes that happened before <span class="event">w</span>. | 323 will observe writes that happened before <span class="event">w</span>. |
324 </p> | 324 </p> |
325 | 325 |
326 <p> | 326 <p> |
327 In this program: | 327 In this program: |
328 </p> | 328 </p> |
329 | 329 |
330 <pre> | 330 <pre> |
331 var a, b int | 331 var a, b int |
332 | 332 |
333 func f() { | 333 func f() { |
334 » a = 1; | 334 » a = 1 |
335 » b = 2; | 335 » b = 2 |
336 } | 336 } |
337 | 337 |
338 func g() { | 338 func g() { |
339 » print(b); | 339 » print(b) |
340 » print(a); | 340 » print(a) |
341 } | 341 } |
342 | 342 |
343 func main() { | 343 func main() { |
344 » go f(); | 344 » go f() |
345 » g(); | 345 » g() |
346 } | 346 } |
347 </pre> | 347 </pre> |
348 | 348 |
349 <p> | 349 <p> |
350 it can happen that <code>g</code> prints <code>2</code> and then <code>0</code>. | 350 it can happen that <code>g</code> prints <code>2</code> and then <code>0</code>. |
351 </p> | 351 </p> |
352 | 352 |
353 <p> | 353 <p> |
354 This fact invalidates a few common idioms. | 354 This fact invalidates a few common idioms. |
355 </p> | 355 </p> |
356 | 356 |
357 <p> | 357 <p> |
358 Double-checked locking is an attempt to avoid the overhead of synchronization. | 358 Double-checked locking is an attempt to avoid the overhead of synchronization. |
359 For example, the <code>twoprint</code> program might be | 359 For example, the <code>twoprint</code> program might be |
360 incorrectly written as: | 360 incorrectly written as: |
361 </p> | 361 </p> |
362 | 362 |
363 <pre> | 363 <pre> |
364 var a string | 364 var a string |
365 var done bool | 365 var done bool |
366 | 366 |
367 func setup() { | 367 func setup() { |
368 » a = "hello, world"; | 368 » a = "hello, world" |
369 » done = true; | 369 » done = true |
370 } | 370 } |
371 | 371 |
372 func doprint() { | 372 func doprint() { |
373 if !done { | 373 if !done { |
374 » » once.Do(setup); | 374 » » once.Do(setup) |
375 } | 375 } |
376 » print(a); | 376 » print(a) |
377 } | 377 } |
378 | 378 |
379 func twoprint() { | 379 func twoprint() { |
380 » go doprint(); | 380 » go doprint() |
381 » go doprint(); | 381 » go doprint() |
382 } | 382 } |
383 </pre> | 383 </pre> |
384 | 384 |
385 <p> | 385 <p> |
386 but there is no guarantee that, in <code>doprint</code>, observing the write to
<code>done</code> | 386 but there is no guarantee that, in <code>doprint</code>, observing the write to
<code>done</code> |
387 implies observing the write to <code>a</code>. This | 387 implies observing the write to <code>a</code>. This |
388 version can (incorrectly) print an empty string | 388 version can (incorrectly) print an empty string |
389 instead of <code>"hello, world"</code>. | 389 instead of <code>"hello, world"</code>. |
390 </p> | 390 </p> |
391 | 391 |
392 <p> | 392 <p> |
393 Another incorrect idiom is busy waiting for a value, as in: | 393 Another incorrect idiom is busy waiting for a value, as in: |
394 </p> | 394 </p> |
395 | 395 |
396 <pre> | 396 <pre> |
397 var a string | 397 var a string |
398 var done bool | 398 var done bool |
399 | 399 |
400 func setup() { | 400 func setup() { |
401 » a = "hello, world"; | 401 » a = "hello, world" |
402 » done = true; | 402 » done = true |
403 } | 403 } |
404 | 404 |
405 func main() { | 405 func main() { |
406 » go setup(); | 406 » go setup() |
407 for !done { | 407 for !done { |
408 } | 408 } |
409 » print(a); | 409 » print(a) |
410 } | 410 } |
411 </pre> | 411 </pre> |
412 | 412 |
413 <p> | 413 <p> |
414 As before, there is no guarantee that, in <code>main</code>, | 414 As before, there is no guarantee that, in <code>main</code>, |
415 observing the write to <code>done</code> | 415 observing the write to <code>done</code> |
416 implies observing the write to <code>a</code>, so this program could | 416 implies observing the write to <code>a</code>, so this program could |
417 print an empty string too. | 417 print an empty string too. |
418 Worse, there is no guarantee that the write to <code>done</code> will ever | 418 Worse, there is no guarantee that the write to <code>done</code> will ever |
419 be observed by <code>main</code>, since there are no synchronization | 419 be observed by <code>main</code>, since there are no synchronization |
420 events between the two threads. The loop in <code>main</code> is not | 420 events between the two threads. The loop in <code>main</code> is not |
421 guaranteed to finish. | 421 guaranteed to finish. |
422 </p> | 422 </p> |
423 | 423 |
424 <p> | 424 <p> |
425 There are subtler variants on this theme, such as this program. | 425 There are subtler variants on this theme, such as this program. |
426 </p> | 426 </p> |
427 | 427 |
428 <pre> | 428 <pre> |
429 type T struct { | 429 type T struct { |
430 » msg string; | 430 » msg string |
431 } | 431 } |
432 | 432 |
433 var g *T | 433 var g *T |
434 | 434 |
435 func setup() { | 435 func setup() { |
436 » t := new(T); | 436 » t := new(T) |
437 » t.msg = "hello, world"; | 437 » t.msg = "hello, world" |
438 » g = t; | 438 » g = t |
439 } | 439 } |
440 | 440 |
441 func main() { | 441 func main() { |
442 » go setup(); | 442 » go setup() |
443 for g == nil { | 443 for g == nil { |
444 } | 444 } |
445 » print(g.msg); | 445 » print(g.msg) |
446 } | 446 } |
447 </pre> | 447 </pre> |
448 | 448 |
449 <p> | 449 <p> |
450 Even if <code>main</code> observes <code>g != nil</code> and exits its loop, | 450 Even if <code>main</code> observes <code>g != nil</code> and exits its loop, |
451 there is no guarantee that it will observe the initialized | 451 there is no guarantee that it will observe the initialized |
452 value for <code>g.msg</code>. | 452 value for <code>g.msg</code>. |
453 </p> | 453 </p> |
454 | 454 |
455 <p> | 455 <p> |
456 In all these examples, the solution is the same: | 456 In all these examples, the solution is the same: |
457 use explicit synchronization. | 457 use explicit synchronization. |
458 </p> | 458 </p> |
OLD | NEW |