summaryrefslogtreecommitdiff
path: root/src/sync
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2022-01-26 16:53:50 -0500
committerGopher Robot <gobot@golang.org>2022-06-06 20:48:03 +0000
commita71ca3dfbd32faf351ff68bcc26a4d5abd9b06d7 (patch)
tree0523f7aeacea7089b127ea3a8e5e58dded85fa0e /src/sync
parent3651a6117e9a88576615c29c4faf7eeec55d7691 (diff)
downloadgo-git-a71ca3dfbd32faf351ff68bcc26a4d5abd9b06d7.tar.gz
runtime, sync, sync/atomic: document happens-before guarantees
A few of these are copied from the memory model doc. Many are entirely new, following discussion on #47141. See https://research.swtch.com/gomm for background. The rule we are establishing is that each type that is meant to help synchronize a Go program should document its happens-before guarantees. For #50859. Change-Id: I947c40639b263abe67499fa74f68711a97873a39 Reviewed-on: https://go-review.googlesource.com/c/go/+/381316 Auto-Submit: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org>
Diffstat (limited to 'src/sync')
-rw-r--r--src/sync/atomic/doc.go8
-rw-r--r--src/sync/cond.go8
-rw-r--r--src/sync/map.go7
-rw-r--r--src/sync/mutex.go7
-rw-r--r--src/sync/once.go4
-rw-r--r--src/sync/pool.go5
-rw-r--r--src/sync/rwmutex.go8
-rw-r--r--src/sync/waitgroup.go3
8 files changed, 49 insertions, 1 deletions
diff --git a/src/sync/atomic/doc.go b/src/sync/atomic/doc.go
index bb3b8f673e..4d426826da 100644
--- a/src/sync/atomic/doc.go
+++ b/src/sync/atomic/doc.go
@@ -36,6 +36,14 @@
// The load and store operations, implemented by the LoadT and StoreT
// functions, are the atomic equivalents of "return *addr" and
// "*addr = val".
+//
+// In the terminology of the Go memory model, if the effect of
+// an atomic operation A is observed by atomic operation B,
+// then A “synchronizes before” B.
+// Additionally, all the atomic operations executed in a program
+// behave as though executed in some sequentially consistent order.
+// This definition provides the same semantics as
+// C++'s sequentially consistent atomics and Java's volatile variables.
package atomic
import (
diff --git a/src/sync/cond.go b/src/sync/cond.go
index 841be96896..19f986e478 100644
--- a/src/sync/cond.go
+++ b/src/sync/cond.go
@@ -18,6 +18,10 @@ import (
// when calling the Wait method.
//
// A Cond must not be copied after first use.
+//
+// In the terminology of the Go memory model, Cond arranges that
+// a call to Broadcast or Signal “synchronizes before” any Wait call
+// that it unblocks.
type Cond struct {
noCopy noCopy
@@ -85,11 +89,13 @@ func (c *copyChecker) check() {
}
}
-// noCopy may be embedded into structs which must not be copied
+// noCopy may be added to structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
+//
+// Note that it must not be embedded, due to the Lock and Unlock methods.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
diff --git a/src/sync/map.go b/src/sync/map.go
index 2fa3253429..ec529e056b 100644
--- a/src/sync/map.go
+++ b/src/sync/map.go
@@ -24,6 +24,13 @@ import (
// contention compared to a Go map paired with a separate Mutex or RWMutex.
//
// The zero Map is empty and ready for use. A Map must not be copied after first use.
+//
+// In the terminology of the Go memory model, Map arranges that a write operation
+// “synchronizes before” any read operation that observes the effect of the write, where
+// read and write operations are defined as follows.
+// Load, LoadAndDelete, LoadOrStore are read operations;
+// Delete, LoadAndDelete, and Store are write operations;
+// and LoadOrStore is a write operation when it returns loaded set to false.
type Map struct {
mu Mutex
diff --git a/src/sync/mutex.go b/src/sync/mutex.go
index 80bb827054..2ea024e585 100644
--- a/src/sync/mutex.go
+++ b/src/sync/mutex.go
@@ -24,6 +24,13 @@ func fatal(string)
// The zero value for a Mutex is an unlocked mutex.
//
// A Mutex must not be copied after first use.
+//
+// In the terminology of the Go memory model,
+// the n'th call to Unlock “synchronizes before” the m'th call to Lock
+// for any n < m.
+// A successful call to TryLock is equivalent to a call to Lock.
+// A failed call to TryLock does not establish any “synchronizes before”
+// relation at all.
type Mutex struct {
state int32
sema uint32
diff --git a/src/sync/once.go b/src/sync/once.go
index 38373160b9..b6399cfc3d 100644
--- a/src/sync/once.go
+++ b/src/sync/once.go
@@ -11,6 +11,10 @@ import (
// Once is an object that will perform exactly one action.
//
// A Once must not be copied after first use.
+//
+// In the terminology of the Go memory model,
+// the return from f “synchronizes before”
+// the return from any call of once.Do(f).
type Once struct {
// done indicates whether the action has been performed.
// It is first in the struct because it is used in the hot path.
diff --git a/src/sync/pool.go b/src/sync/pool.go
index ea142bb181..cf01e2e189 100644
--- a/src/sync/pool.go
+++ b/src/sync/pool.go
@@ -41,6 +41,11 @@ import (
// free list.
//
// A Pool must not be copied after first use.
+//
+// In the terminology of the Go memory model, a call to Put(x) “synchronizes before”
+// a call to Get returning that same value x.
+// Similarly, a call to New returning x “synchronizes before”
+// a call to Get returning that same value x.
type Pool struct {
noCopy noCopy
diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go
index 7b10808ec4..e914f3eba0 100644
--- a/src/sync/rwmutex.go
+++ b/src/sync/rwmutex.go
@@ -25,6 +25,14 @@ import (
// recursive read locking. This is to ensure that the lock eventually becomes
// available; a blocked Lock call excludes new readers from acquiring the
// lock.
+//
+// In the terminology of the Go memory model,
+// the n'th call to Unlock “synchronizes before” the m'th call to Lock
+// for any n < m, just as for Mutex.
+// For any call to RLock, there exists an n such that
+// the n'th call to Unlock “synchronizes before” that call to RLock,
+// and the corresponding call to RUnlock “synchronizes before”
+// the n+1'th call to Lock.
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // semaphore for writers to wait for completing readers
diff --git a/src/sync/waitgroup.go b/src/sync/waitgroup.go
index 9c6662d04b..9f26ae106c 100644
--- a/src/sync/waitgroup.go
+++ b/src/sync/waitgroup.go
@@ -17,6 +17,9 @@ import (
// Wait can be used to block until all goroutines have finished.
//
// A WaitGroup must not be copied after first use.
+//
+// In the terminology of the Go memory model, a call to Done
+// “synchronizes before” the return of any Wait call that it unblocks.
type WaitGroup struct {
noCopy noCopy