并发编程

基本原则

  1. 控制临界区的纯度
  2. 控制临界区的粒度
  3. 减少临界区代码的执行时间
  4. 避免长时间持有互斥量
  5. 优先使用原子操作而不是互斥量

uint32 是原子操作方法支持的最短数值类型,可用于节省计数器的空间

超时控制

使用 context 包对多个 G 进行超时优雅退出

不额外启用 G 的情况下实现超时判断? 使用 CAS 操作比较是否为原状态,如果超时,状态会被修改至其他状态,否则就没有超时

一个容易犯的错误:在 for-select 结构里面使用 <-time.After(),这会导致内存泄露,因为在计时器触发之前,GC并不会回收 timer!

func ProcessChannelMessages(ctx context.Context, in <-chan string, idleCounter prometheus.Counter) {
    idleDuration := 5 * time.Minute
    idleDelay := time.NewTimer(idleDuration)
	// 记得停止定时器
    defer idleDelay.Stop()
    for {
		// 在时间过期后重置并激活同一定时器
        idleDelay.Reset(idleDuration)
        select {
        case s, ok := <-in:
            if !ok {
                return
            }
		// 等待定时器超时
        case <-idleDelay.C:
            idleCounter.Inc()
        case <-ctx.Done():
            return
        }
    }
}