mirror of
https://github.com/golang/go
synced 2024-11-17 01:24:50 -07:00
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>
This commit is contained in:
parent
3651a6117e
commit
a71ca3dfbd
@ -321,11 +321,23 @@ func runfinq() {
|
|||||||
// closing p.d, causing syscall.Write to fail because it is writing to
|
// closing p.d, causing syscall.Write to fail because it is writing to
|
||||||
// a closed file descriptor (or, worse, to an entirely different
|
// a closed file descriptor (or, worse, to an entirely different
|
||||||
// file descriptor opened by a different goroutine). To avoid this problem,
|
// file descriptor opened by a different goroutine). To avoid this problem,
|
||||||
// call runtime.KeepAlive(p) after the call to syscall.Write.
|
// call KeepAlive(p) after the call to syscall.Write.
|
||||||
//
|
//
|
||||||
// A single goroutine runs all finalizers for a program, sequentially.
|
// A single goroutine runs all finalizers for a program, sequentially.
|
||||||
// If a finalizer must run for a long time, it should do so by starting
|
// If a finalizer must run for a long time, it should do so by starting
|
||||||
// a new goroutine.
|
// a new goroutine.
|
||||||
|
//
|
||||||
|
// In the terminology of the Go memory model, a call
|
||||||
|
// SetFinalizer(x, f) “synchronizes before” the finalization call f(x).
|
||||||
|
// However, there is no guarantee that KeepAlive(x) or any other use of x
|
||||||
|
// “synchronizes before” f(x), so in general a finalizer should use a mutex
|
||||||
|
// or other synchronization mechanism if it needs to access mutable state in x.
|
||||||
|
// For example, consider a finalizer that inspects a mutable field in x
|
||||||
|
// that is modified from time to time in the main program before x
|
||||||
|
// becomes unreachable and the finalizer is invoked.
|
||||||
|
// The modifications in the main program and the inspection in the finalizer
|
||||||
|
// need to use appropriate synchronization, such as mutexes or atomic updates,
|
||||||
|
// to avoid read-write races.
|
||||||
func SetFinalizer(obj any, finalizer any) {
|
func SetFinalizer(obj any, finalizer any) {
|
||||||
if debug.sbrk != 0 {
|
if debug.sbrk != 0 {
|
||||||
// debug.sbrk never frees memory, so no finalizers run
|
// debug.sbrk never frees memory, so no finalizers run
|
||||||
|
@ -36,6 +36,14 @@
|
|||||||
// The load and store operations, implemented by the LoadT and StoreT
|
// The load and store operations, implemented by the LoadT and StoreT
|
||||||
// functions, are the atomic equivalents of "return *addr" and
|
// functions, are the atomic equivalents of "return *addr" and
|
||||||
// "*addr = val".
|
// "*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
|
package atomic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -18,6 +18,10 @@ import (
|
|||||||
// when calling the Wait method.
|
// when calling the Wait method.
|
||||||
//
|
//
|
||||||
// A Cond must not be copied after first use.
|
// 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 {
|
type Cond struct {
|
||||||
noCopy noCopy
|
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.
|
// after the first use.
|
||||||
//
|
//
|
||||||
// See https://golang.org/issues/8005#issuecomment-190753527
|
// See https://golang.org/issues/8005#issuecomment-190753527
|
||||||
// for details.
|
// for details.
|
||||||
|
//
|
||||||
|
// Note that it must not be embedded, due to the Lock and Unlock methods.
|
||||||
type noCopy struct{}
|
type noCopy struct{}
|
||||||
|
|
||||||
// Lock is a no-op used by -copylocks checker from `go vet`.
|
// Lock is a no-op used by -copylocks checker from `go vet`.
|
||||||
|
@ -24,6 +24,13 @@ import (
|
|||||||
// contention compared to a Go map paired with a separate Mutex or RWMutex.
|
// 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.
|
// 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 {
|
type Map struct {
|
||||||
mu Mutex
|
mu Mutex
|
||||||
|
|
||||||
|
@ -24,6 +24,13 @@ func fatal(string)
|
|||||||
// The zero value for a Mutex is an unlocked mutex.
|
// The zero value for a Mutex is an unlocked mutex.
|
||||||
//
|
//
|
||||||
// A Mutex must not be copied after first use.
|
// 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 {
|
type Mutex struct {
|
||||||
state int32
|
state int32
|
||||||
sema uint32
|
sema uint32
|
||||||
|
@ -11,6 +11,10 @@ import (
|
|||||||
// Once is an object that will perform exactly one action.
|
// Once is an object that will perform exactly one action.
|
||||||
//
|
//
|
||||||
// A Once must not be copied after first use.
|
// 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 {
|
type Once struct {
|
||||||
// done indicates whether the action has been performed.
|
// done indicates whether the action has been performed.
|
||||||
// It is first in the struct because it is used in the hot path.
|
// It is first in the struct because it is used in the hot path.
|
||||||
|
@ -41,6 +41,11 @@ import (
|
|||||||
// free list.
|
// free list.
|
||||||
//
|
//
|
||||||
// A Pool must not be copied after first use.
|
// 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 {
|
type Pool struct {
|
||||||
noCopy noCopy
|
noCopy noCopy
|
||||||
|
|
||||||
|
@ -25,6 +25,14 @@ import (
|
|||||||
// recursive read locking. This is to ensure that the lock eventually becomes
|
// recursive read locking. This is to ensure that the lock eventually becomes
|
||||||
// available; a blocked Lock call excludes new readers from acquiring the
|
// available; a blocked Lock call excludes new readers from acquiring the
|
||||||
// lock.
|
// 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 {
|
type RWMutex struct {
|
||||||
w Mutex // held if there are pending writers
|
w Mutex // held if there are pending writers
|
||||||
writerSem uint32 // semaphore for writers to wait for completing readers
|
writerSem uint32 // semaphore for writers to wait for completing readers
|
||||||
|
@ -17,6 +17,9 @@ import (
|
|||||||
// Wait can be used to block until all goroutines have finished.
|
// Wait can be used to block until all goroutines have finished.
|
||||||
//
|
//
|
||||||
// A WaitGroup must not be copied after first use.
|
// 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 {
|
type WaitGroup struct {
|
||||||
noCopy noCopy
|
noCopy noCopy
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user