1. Home
  2. Docs
  3. golang
  4. 内置库(包-package)
  5. sync

sync

包sync提供了基本的同步基元,如互斥锁。除了Once和WaitGroup类型外,大多数都是为低级别的库例程所使用的。更高级别的同步最好通过通道和通信来完成。

包含在这个包中定义的类型的值不应该被复制。

type Cond

Cond实现了一个条件变量,是等待或宣布事件发生的Goroutines的汇合点。

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

一个Cond在第一次使用后不能被复制。

func NewCond

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

func (*Cond) Broadcast

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

在呼叫过程中,允许但不要求呼叫者持有c.L

func (*Cond) Signal

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

在呼叫过程中,允许但不要求呼叫者持有c.L。

func (*Cond) Wait

Wait以原子方式解锁c.L,并暂停调用goroutine的执行。在后来恢复执行后,Wait在返回前锁定c.L。与其他系统不同,Wait不能返回,除非被Broadcast或Signal唤醒。

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

type Locker

type Locker interface {
    Lock()
    Unlock()
}

锁定器代表一个可以被锁定和解锁的对象。

type Map

Map就像Go中的map[interface{}]interface{},但对于多个goroutine的并发使用是安全的,不需要额外的锁定或协调。加载、存储和删除在摊销后的恒定时间内运行。

map类型是专门的。大多数代码应该使用普通的Go-map,而不是单独的锁定或协调,以获得更好的类型安全性,并使其更容易与map内容一起维护其他不变量。

map类型针对两种常见的使用情况进行了优化。(1)当一个给定的键的条目只被写入一次但被多次读取时,就像在只会增长的缓存中,或者(2)当多个goroutines读取、写入和覆盖不相干的键集合的条目时。在这两种情况下,与Go map搭配单独的Mutex或RWMutex相比,使用Map可以大大减少锁的争夺。

零Map是空的,可以随时使用。Map在首次使用后不得被复制。

func (*Map) Delete

删掉一个键的值。

func (*Map) Load

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

func (*Map) LoadAndDelete

LoadAndDelete删除一个键的值,如果有的话返回之前的值。载入的结果报告该键是否存在。

func (*Map) LoadOrStore

如果存在的话,LoadOrStore返回键的现有值。否则,它存储并返回给定的值。如果值被加载,加载的结果为真,如果被存储,则为假。

func (*Map) Range

Range对地图中存在的每个键和值依次调用f。如果f返回false,range就停止迭代。

Range不一定对应于地图内容的任何一致的快照:没有一个键会被访问一次以上,但是如果任何键的值被同时存储或删除,Range可能反映该键在Range调用过程中任何点的任何映射。

即使f在调用次数不变的情况下返回false,Range也可能是O(N)与地图中的元素数量有关。

func (*Map) Store

存储设置一个键的值。

type Mutex

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

一个Mutex在第一次使用后不能被复制。

func (*Mutex) Lock

如果锁已经被使用,调用的goroutine就会阻塞,直到mutex可用。

func (*Mutex) Unlock

如果m在进入Unlock时没有被锁定,那是一个运行时错误。

一个被锁定的Mutex并不与一个特定的goroutine相关联。允许一个goroutine锁定一个Mutex,然后安排另一个goroutine来解锁它。

type Once

func (*Once) Do

当且仅当Do在Once的这个实例中被首次调用时,Do才会调用函数f。换句话说,鉴于

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

Do是为必须精确运行一次的初始化准备的。由于f是niladic,可能有必要使用一个函数字面来捕获将被Do调用的函数的参数。

因为在对f的一个调用返回之前,对Do的任何调用都不会返回,如果f导致Do被调用,它将陷入僵局。

如果f慌了,Do认为它已经返回了;未来对Do的调用会返回而不调用f。

type Pool

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

存储在Pool中的任何项目都可能在任何时候被自动删除,而不需要通知。如果发生这种情况时,Pool持有唯一的引用,那么该项目可能会被取消分配。

一个Pool对于多个goroutine同时使用是安全的。

Pool的目的是缓存已分配但未使用的项目,以便以后再使用,减轻垃圾收集器的压力。也就是说,它使建立高效、线程安全的空闲列表变得容易。然而,它并不适合于所有的自由列表。

池的一个合适的用途是管理一组临时项目,这些临时项目在包的独立客户端之间默默地共享,并有可能被重复使用。Pool提供了一种在许多客户端之间分摊分配开销的方法。

一个很好的使用Pool的例子是在fmt包中,它维护一个动态大小的临时输出缓冲区的存储。存储器在负载下(当许多goroutines积极打印时)会扩大,而在静止时则会缩小。

另一方面,作为短命对象的一部分而维护的自由列表并不是Pool的合适用途,因为在这种情况下,开销并不能很好地摊销。让这些对象实现自己的自由列表会更有效率。

一个Pool在第一次使用后不能被复制。

func (*Pool) Get

Get从池中选择一个任意的项目,将其从池中移除,并将其返回给调用者。Get可以选择忽略池子并将其视为空的。调用者不应该假设传递给Put的值和Get返回的值之间有任何关系。

如果Get将返回nil,并且p.New不是nil,Get将返回调用p.New的结果。

func (*Pool) Put

type RWMutex

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

一个RWMutex在第一次使用后不能被复制。

如果一个goroutine持有一个RWMutex用于读取,而另一个goroutine可能会调用Lock,那么在最初的读取锁被释放之前,没有一个goroutine应该期望能够获得一个读取锁。特别是,这禁止了递归读锁。这是为了确保锁最终是可用的;一个阻塞的Lock调用排除了新的读者获取锁的可能性。

func (*RWMutex) Lock

Lock锁住rw进行写入。如果该锁已经被锁定用于读或写,Lock会阻止,直到该锁可用。

func (*RWMutex) RLock

RLock锁住rw进行读取。

它不应该被用于递归读锁;一个阻塞的Lock调用排除了新的读者获得该锁。参见关于RWMutex类型的文档。

func (*RWMutex) RLocker

RLocker返回一个Locker接口,通过调用rw.RLock和rw.RUnlock实现锁定和解锁方法。

func (*RWMutex) RUnlock

RUnlock撤消单个RLock调用;它不影响其他同时进行的读者。如果rw在进入RUnlock时没有被锁定用于读取,那是一个运行时错误。

func (*RWMutex) Unlock

解锁为写而解锁rw。如果rw在进入Unlock时没有被锁定用于写入,这将是一个运行时错误。

与Mutexes一样,一个被锁定的RWMutex并不与一个特定的goroutine相关。一个goroutine可以RLock(锁定)一个RWMutex,然后安排另一个goroutine来RUnlock(解锁)它。

type WaitGroup

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

一个WaitGroup在第一次使用后不能被复制。

func (*WaitGroup) Add

Add将delta(可能是负数)加入WaitGroup计数器。如果该计数器变为零,所有在Wait上阻塞的goroutines都被释放。如果计数器变成负数,Add就会惊慌失措。

请注意,当计数器为零时发生的具有正数delta的调用必须发生在Wait之前。负delta的调用,或者在计数器大于0时开始的正delta的调用,可以在任何时间发生。通常,这意味着对Add的调用应该在创建goroutine或其他要等待的事件的语句之前执行。如果一个WaitGroup被重复使用以等待几个独立的事件集,新的Add调用必须在所有先前的Wait调用返回之后发生。参见WaitGroup的例子。

func (*WaitGroup) Done

Done将WaitGroup计数器递减1。

func (*WaitGroup) Wait

等待块,直到WaitGroup计数器为零。

Was this article helpful to you? Yes No

How can we help?