条件变量
sync.Cond类型代表了条件变量。其中有三个方法
- Wait、Signal、Broadcast分别代表了等待通知、单发通知和广播通知等操作。
方法Wait会自动地对与该条件变量关联的那个锁进行解锁,并且使用调用方所在的Gorountine被阻塞,一旦该方收到通知,就会试图再次锁定该锁。如果锁定成功,它就会唤醒那个被它阻塞的Gorountine。否则,该方法会等待下一个通知,那个Gorountine也会继续阻塞。
方法Signal和Broadcast的作用都是发送通知以唤醒正在为此而被阻塞的Gorountine。不同的是前者目标只有一个,而后者的目标则是所有。
原子操作
原子操作即进行过程中不能被中断的操作。针对某个值的原子操作在被进行的过程中,CPU绝不会再去进行其他的针对该值的操作。原子操作仅会由一个独立的CPU指令代表和完成,以保证并发下原子操作的绝对安全。
我们可以通过调用函数对几种简单的类型的值进行原子操作。这些类型包括int32、int64、uint32、uint64、uintptr和unsafe.Pointer类型,共6种。
一共有5种类型的的原子操作:
- 增或减:实现对被操作值的增大或者减小。
- 比较并交换:Compare And Swap (CAS)会先判断被操作值和参数old的值是否相等,如果相等才会用参数new的值替换旧的值。
- 载入:读取,接受一个指针,并返回该指针值指向的那个值。
- 存储:写入, 接受一个指针,向指针值指向地址写入新值。
- 交换:与CAS的操作不同,原子交换操作不会关心被操作的旧值。它会直接设置新值。但它又比原子载入多做了一步。作为交换,它会返回被操作值的旧值。
Sync.Once
该类型的方法Do可以接受一个无参数、无结果的函数作为其参数。针对Sync.Once类型值的指针方法Do的有效调用次数永远会是1次。也就是说,无论我们调用这个方法多少次,也无论我们在多次调用时传递给它的参数值是否相同,都仅有一次调用是有效的。
这个Sync.Once类型的典型应用场景就是执行仅需要执行一次的任务。例如,数据库连接池的初始化任务。
Sync.Once提供的功能是有互斥锁和原子操作来实现的。