在线文档教程

同步 | sync

打包 sync

  • import "sync"

  • 概观

  • 索引

  • 示例

  • 子目录

概观

程序包 sync 提供基本的同步原语,如互斥锁。除了 Once 和 WaitGroup 类型之外,大多数类型都是供低级库例程使用的。通过 Channel 和沟通可以更好地完成更高级别的同步。

包含此程序包中定义的类型的值不应被复制。

索引

  • type Cond

  • func NewCond(l Locker) *Cond

  • func (c *Cond) Broadcast()

  • func (c *Cond) Signal()

  • func (c *Cond) Wait()

  • type Locker

  • type Map

  • func (m *Map) Delete(key interface{})

  • func (m *Map) Load(key interface{}) (value interface{}, ok bool)

  • func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)

  • func (m *Map) Range(f func(key, value interface{}) bool)

  • func (m *Map) Store(key, value interface{})

  • type Mutex

  • func (m *Mutex) Lock()

  • func (m *Mutex) Unlock()

  • type Once

  • func (o *Once) Do(f func())

  • type Pool

  • func (p *Pool) Get() interface{}

  • func (p *Pool) Put(x interface{})

  • type RWMutex

  • func (rw *RWMutex) Lock()

  • func (rw *RWMutex) RLock()

  • func (rw *RWMutex) RLocker() Locker

  • func (rw *RWMutex) RUnlock()

  • func (rw *RWMutex) Unlock()

  • type WaitGroup

  • func (wg *WaitGroup) Add(delta int)

  • func (wg *WaitGroup) Done()

  • func (wg *WaitGroup) Wait()

示例

一旦 Pool WaitGroup

打包文件

cond.go map.go mutex.go once.go pool.go runtime.go rwmutex.go waitgroup.go

type Cond Source

Cond 实现了一个条件变量,用于等待或通告事件发生的 goroutine 的集合点。

每个 Cond 都有一个关联的 Locker L (通常是 * Mutex 或 * RWMutex ),在更改条件和调用 Wait 方法时必须保持该 L。

首次使用后不得复制 Cond 。

type Cond struct { // L is held while observing or changing the condition L Locker // contains filtered or unexported fields }

func NewCondSource

func NewCond(l Locker) *Cond

NewCond 返回一个带有 Locker L 的新 Cond 。

func (*Cond) BroadcastSource

func (c *Cond) Broadcast()

广播唤醒等待的所有 goroutines c 。

在通话过程中,主叫方可以允许但不是必需的。

func (*Cond) SignalSource

func (c *Cond) Signal()

如果有任何信号,信号唤醒一个等待在 c 上的 goroutine 。

在调用过程中,调用方可以允许但不是必需的。

func (*Cond) WaitSource

func (c *Cond) Wait()

等待原子的解锁 c.L 并暂停执行调用的 goroutine 。在稍后恢复执行后, Wait 在返回之前锁定 c.L 。与其他系统不同,除非广播或信号唤醒,否则 Wait 不能返回。

因为当 Wait 第一次恢复时 c.L 没有被锁定,所以当 Wait 返回时,调用者通常不能认为条件为真。相反,调用者应该等待一个循环:

c.L.Lock() for !condition() { c.Wait() } ... make use of condition ... c.L.Unlock()

键入LockerSource

Locker 表示可以锁定和解锁的物体。

type Locker interface { Lock() Unlock() }

键入MapSource

Map 是一个并发映射,包含分期恒定时间加载,存储和删除。多个 goroutines 同时调用 Map 的方法是安全的。

它针对并发循环进行了优化,使用的密钥随时间保持稳定,并且只有少数稳态存储,或者每个密钥存储在一个 goroutine 中。

对于不共享这些属性的用例,与使用读写互斥锁配对的普通映射相比,它可能具有可比较或更差的性能以及更差的类型安全性。

零映射有效且为空。

首次使用后不得复制 Map 。

type Map struct { // contains filtered or unexported fields }

func (*Map) DeleteSource

func (m *Map) Delete(key interface{})

Delete 删除键的值。

func (*Map) LoadSource

func (m *Map) Load(key interface{}) (value interface{}, ok bool)

加载返回键映射中存储的值,如果没有值,则返回零。ok 的结果表示在地图中是否找到了值。

func (*Map) LoadOrStoreSource

func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)

LoadOrStore 返回键的现有值(如果存在)。否则,它存储并返回给定的值。如果加载的值加载结果为 true ,如果存储则加载为 false 。

func (*Map) RangeSource

func (m *Map) Range(f func(key, value interface{}) bool)

范围按顺序为地图中存在的每个键和值调用 f 。如果 f 返回 false ,范围将停止迭代。

范围不一定对应于 Map 内容的任何一致快照:不会有多次访问密钥,但如果同时存储或删除任何密钥的值,则范围可能反映该范围内任何点的该密钥的任何映射调用。

范围可能是 O(N) 与映射中的元素数量,即使f在常数调用后返回 false 也是如此。

func (*Map) StoreSource

func (m *Map) Store(key, value interface{})

存储设置密钥的值。

键入Mutex Source

Mutex 是互斥锁。Mutex 的零值是一个解锁的互斥锁。

第一次使用后不得复制 Mutex 。

type Mutex struct { // contains filtered or unexported fields }

func (*Mutex) Lock Source

func (m *Mutex) Lock()

Lock 锁住 m 。如果锁已在使用中,则调用 goroutine 将阻塞,直到互斥锁可用。

func (*Mutex) UnlockSource

func (m *Mutex) Unlock()

Unlock 解锁 m 。如果 m 未锁定进入解锁,则为运行时错误。

锁定的互斥锁与特定的 goroutine 没有关联。允许一个 goroutine 锁定一个 Mutex ,然后安排另一个 goroutine 来解锁它。

键入OnceSource

一旦一个对象会执行一个动作。

type Once struct { // contains filtered or unexported fields }

示例

package main import ( "fmt" "sync" ) func main() { var once sync.Once onceBody := func() { fmt.Println("Only once") } done := make(chan bool) for i := 0; i < 10; i++ { go func() { once.Do(onceBody) done <- true }() } for i := 0; i < 10; i++ { <-done } }

func (*Once) DoSource

func (o *Once) Do(f func())

当且仅当第一次为这个 Once 实例调用 Do时,才调用函数 f 。换句话说,给出

var once Once

如果一次 .Do(f) 被多次调用,只有第一次调用会调用f,即使 f 在每次调用中都有不同的值。一个新的实例需要执行每个函数。

Do 是用于初始化的,只能运行一次。由于 f 是 niladic,因此可能需要使用函数文字来捕获由 Do 调用的函数的参数:

config.once.Do(func() { config.init(filename) })

由于没有对 Do 的调用返回,直到对 f 的一次调用返回,如果 f 导致 Do 被调用,它将会死锁。

如果 f 终止, Do 认为它已经返回; 未来的调用返回而不调用 f 。

键入PoolSource

Pool 是一组可以单独保存和检索的临时对象。

存储在 Pool 中的任何项目可能会随时自动删除,而无需通知。如果 Pool 在这种情况发生时只有唯一的引用,则该项可能会被释放。

Pool 可以同时用于多个 goroutine 。

Pool 的目的是缓存已分配但未使用的项目以备后用,以减轻垃圾收集器的压力。也就是说,它可以轻松构建高效,线程安全的免费列表。但是,它不适用于所有不受限制的列表。

Pool 的适当使用是管理一组临时项目,这些临时项目在一个程序包的并发独立客户端之间悄悄共享并可能被重用。Pool 提供了一种方法来缓解跨多个客户端的分配开销。

fmt 包中有一个很好地使用 Pool 的例子,它维护一个动态大小的临时输出缓冲区存储区。商店在负载下(当许多 goroutines 正在活动时)缩小,静止时缩小。

另一方面,作为短期对象的一部分而维护的空闲列表对于 Pool 来说并不适合,因为在该场景中开销不能很好地分摊。让这些对象实现自己的不受限制的列表会更高效。

首次使用后不得复制 Pool 。

type Pool struct { // New optionally specifies a function to generate // a value when Get would otherwise return nil. // It may not be changed concurrently with calls to Get. New func() interface{} // contains filtered or unexported fields }

示例

package main import ( "bytes" "io" "os" "sync" "time" ) var bufPool = sync.Pool{ New: func() interface{} { // The Pool's New function should generally only return pointer // types, since a pointer can be put into the return interface // value without an allocation: return new(bytes.Buffer) }, } // timeNow is a fake version of time.Now for tests. func timeNow() time.Time { return time.Unix(1136214245, 0) } func Log(w io.Writer, key, val string) { b := bufPool.Get().(*bytes.Buffer) b.Reset() // Replace this with time.Now() in a real logger. b.WriteString(timeNow().UTC().Format(time.RFC3339)) b.WriteByte(' ') b.WriteString(key) b.WriteByte('=') b.WriteString(val) w.Write(b.Bytes()) bufPool.Put(b) } func main() { Log(os.Stdout, "path", "/search?q=flowers") }

func (*Pool) GetSource

func (p *Pool) Get() interface{}

从 Pool 中选择一个任意项目,将其从池中删除,并将其返回给调用者。获取可能会选择忽略 Pool 并将其视为空。调用者不应承担传递给 Put 的值与 Get 返回的值之间的任何关系。

如果 Get 以其他方式返回 nil ,并且 p.New 不为零,则 Get 返回调用 p.New 的结果。

func (*Pool) Put Source

func (p *Pool) Put(x interface{})

Put 将 x 添加到 Pool 中。

键入RWMutexSource

RWMutex 是读写器互斥锁。该锁可以由任意数量的读者或单个作者持有。 RWMutex 的零值是一个解锁的互斥锁。

首次使用后,RWMutex 不得被复制。

如果一个 goroutine 持有一个 RWMutex 用于读取,另一个 goroutine 可能调用 Lock ,那么在最初的读取锁定被释放之前,没有 goroutine 应该期望能够获得读取锁定。特别是,这禁止了递归读取锁定。这是为了确保锁最终可用; 被锁定的锁定呼叫不包括新读取器获取锁定。

type RWMutex struct { // contains filtered or unexported fields }

func (*RWMutex) LockSource

func (rw *RWMutex) Lock()

Lock 锁定 rw 写入。如果锁已被锁定以进行读取或写入,则 Lock 块直到锁可用。

func (*RWMutex) RLockSource

func (rw *RWMutex) RLock()

RLock 锁定 rw 阅读。

它不应该用于递归读锁定;被锁定的锁定呼叫不包括新读取器获取锁定。请参阅 RWMutex 类型的文档。

func (*RWMutex) RLockerSource

func (rw *RWMutex) RLocker() Locker

RLocker 通过调用 rw.RLock 和 rw.RUnlock 返回一个实现 Lock 和 Unlock 方法的 Locker 接口。

func (*RWMutex) RUnlockSource

func (rw *RWMutex) RUnlock()

RUnlock 撤销了一次单独的 RLock 调用; 它不会影响其他同时阅读。如果 rw 没有被锁定读入 RUnlock,那么这是一个运行时错误。

func (*RWMutex) Unlock Source

func (rw *RWMutex) Unlock()

Unlock 解锁 rw 写入。如果 rw 没有被锁定写入Unlock,那么这是一个运行时错误。

与 Mutexes 一样,锁定的 RWMutex 与特定的 goroutine 没有关联。一个例程可以 RLock (锁定)一个 RWMutex ,然后安排另一个例程来 RUnlock (解锁)它。

键入WaitGroupSource

WaitGroup 等待一系列 goroutine 完成。主要的 goroutine 调用 Add 来设置要等待的 goroutines 的数量。然后,每个 goroutines 运行并在完成时调用完成。同时,Wait 可以用来阻塞,直到所有的 goroutines 都完成。

首次使用后,不得复制 WaitGroup 。

type WaitGroup struct { // contains filtered or unexported fields }

示例

本示例同时提取多个 URL ,使用 WaitGroup 进行阻塞,直到所有提取完成。

编码:

var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { // Increment the WaitGroup counter. wg.Add(1) // Launch a goroutine to fetch the URL. go func(url string) { // Decrement the counter when the goroutine completes. defer wg.Done() // Fetch the URL. http.Get(url) }(url) } // Wait for all HTTP fetches to complete. wg.Wait()

func (*WaitGroup) Add Source

func (wg *WaitGroup) Add(delta int)

添加向 WaitGroup 计数器添加可能为负数的增量。如果计数器变为零,则等待的所有程序都被释放。如果计数器变为负值,请添加终止。

请注意,在计数器为零时发生的积极增量的调用必须发生在 Wait. Calls 之前。可以在任何时候发生带有负三角形的调用,或者在计数器大于零时开始的具有正三角形的调用。通常这意味着添加的调用应该在创建 goroutine 或其他要等待的事件的语句之前执行。如果 WaitGroup 被重新使用以等待多个独立的事件集合,则在所有先前的等待调用已经返回之后,必须发生新的添加调用。请参阅 WaitGroup 示例。

func (*WaitGroup) Done Source

func (wg *WaitGroup) Done()

完成将 WaitGroup 计数器递减1。

func (*WaitGroup) Wait Source

func (wg *WaitGroup) Wait()

Wait 块,直到 WaitGroup 计数器为零。

子目录

名称概要

| .. |

| atomic| 打包 atomic 提供了用于实现同步算法的低级 atomic 内存原语。|