通道并非用来取代锁,各有不同使用场景。
通道解决高级别逻辑层次并发架构,锁则用来保护低级别局部代码安全。
●竟态条件:多线程同时读写共享资源(竟态资源)。
●临界区:读写竟态资源的代码片段。
●互斥锁:同一时刻,只有一个线程能进入临界区。
●读写锁:写独占(其他读写均被阻塞),读共享。
●信号量:允许指定数量线程进入临界区。
●自旋锁:失败后,以循环积极尝试。(无上下文切换,小粒度)
●悲观锁:操作前独占锁定。
●乐观锁:假定无竞争,后置检查。(Lock Free, CAS)
标准库 sync 提供了多种锁,另有原子操作等。
●Mutex:互斥锁。
●RWMutex:读写锁。
●WaitGroup:等待一组任务结束。
●Cond:单播或广播唤醒其他任务。
●Once:确保只调用一次(函数)。
●Map:并发安全字典,(少写多读,数据不重叠)
●Pool:对象池。(缓存对象可被回收)
竞争检测
测试阶段,以 -race 编译,注入竞争检查(data race detection)指令。
●有较大性能损失,避免在基准测试和发布版本中使用。
●有不确定性,不能保证百分百测出。
●单元测试有效完整,定期执行竞争检查。
条件变量
内部以计数器和队列作为单播(signal)和广播(broadcast)依据。
引入外部锁作为竟态资源保护,可与其他逻辑同步。
func main() {
var wg sync.WaitGroup
cond := sync.NewCond(&sync.Mutex{})
data := make([]int, 0)
// 1 写
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 5; i++ {
// 保护竟态资源。
cond.L.Lock()
data = append(data, i + 100)
cond.L.Unlock()
// 唤醒一个。
cond.Signal()
}
// 唤醒所有(剩余)。
// cond.Broadcast()
}()
// n 读
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
// 锁定竟态资源。
cond.L.Lock()
// 循环检查是否符合后续操作条件。
// 如条件不符,则继续等待。
for len(data) == 0 {
cond.Wait()
}
x := data[0]
data = data[1:]
cond.L.Unlock()
println(id, ":", x)
}(i)
}
wg.Wait()
}
标签:wg,同步,读写,cond,竟态,go,data,channel From: https://www.cnblogs.com/codestack/p/18187378