Golang使用sync库和原子操作实现同步
发布网友
发布时间:2024-09-30 19:55
我来回答
共1个回答
热心网友
时间:2024-12-03 22:18
每个*sync.Once值有一个Do(f func())方法,该方法接收一个类型为func()的参数。在多个协程中,此方法可以被多次并发执行,参数应为同一个函数值。其中,只有一个调用实参函数将得到调用。被调用函数在任何o.Do()方法调用返回前退出。通常用于确保并发程序中代码执行一次。
一个例子中,Hello仅输出一次,而world!输出五次,且Hello在所有world!之前。
*sync.Mutex和*sync.RWMutex实现sync.Locker接口,拥有Lock()和Unlock()方法,保护数据不被多个协程同时读取和修改。*sync.RWMutex添加RLock()和RUnlock()方法,支持多个读取者并发读取,防止数据同时被写入者和其他访问者使用。
*sync.Mutex使用锁确保数据不被多个协程同时使用。在Counter示例中,Mutex字段确保了字段n不会被多个协程同时使用。
*sync.RWMutex在内部包含写锁和读锁,RLock()和RUnlock()方法允许并发读取,Lock()和Unlock()方法用于加锁和解锁。
使用sync.Mutex和sync.RWMutex实现通知,尽管不是最优雅的实现方式。示例中,Hi确保在Bye前打印。
sync.Cond提供多协程通知机制,维护等待协程队列,Wait()、Signal()和Broadcast()方法用于等待、通知和广播。
原子操作整数在并发环境保证无数据竞争,如并发递增int32值。Add()原子操作确保1000个协程递增后打印1000。
StoreT和LoadT原子操作适用于并发实现setter和getter方法。示例中使用原子操作。
对于无符号整数类型T值的原子减法操作,AddT函数调用的第二个实参需为非负数。SwapT和CompareAndSwapT函数实现置换和比较交换操作。
在Go 1.20之前,64位字原子操作要求内存地址为8字节对齐,但在Go 1.19引入的原子方法操作上,这一要求在32-bit和64-bit架构上总是得到满足。然而,对于32-bit架构上的原子函数操作,这一要求并非总能得到满足。详情请参阅关于Go值的内存布局。