Go光速实战
  • Introduction
  • Golang进阶实战
    • reflect反射实战
    • channel通道实战
      • 1. 如何使用Channel模拟锁
      • 2. 如何使用多协程线程安全并发收集结果
      • 3. 如何控制协程执行顺序
      • 4. 如何控制并发数
      • 5. 统计协程耗时
      • 6. 超时控制
    • 泛型实战
    • 底层原理
      • Go协程调度机制
      • Go channel底层机制
      • Gin洋葱模型
  • Golang微服务实战
    • Gin
    • GRPC
      • proto工具插件集
    • 分布式事务
  • Golang工程化实践
    • 编码规范
    • 目录规范
    • 单元测试
    • 避坑指南
  • Golang设计模式
    • UML
    • 设计原则
    • 创建型
      • 单例模式
      • 工厂模式
    • 结构型
      • 代理模式
      • 建造者模式
      • 装饰器模式
    • 行为型
      • 模板模式
      • 策略模式
    • 选项模式
  • Kubernetes实战
    • 概念
    • 模板
    • Problem
      • 1. Pod里能ping通service IP吗
      • 2. K8S 滚动升级怎么保证零宕机
      • 3. kube-proxy是如何转发流量
    • istio
    • informer
    • kubebuilder
由 GitBook 提供支持
在本页
  1. Golang进阶实战
  2. channel通道实战

1. 如何使用Channel模拟锁

上一页channel通道实战下一页2. 如何使用多协程线程安全并发收集结果

最后更新于3年前

这有帮助吗?

CtrlK

这有帮助吗?

此开源图书由ithaiq原创,创作不易转载请注明出处

  1. 我们封装一个struct操作mutex锁

type Test struct {
	count int
	g sync.Mutex
}

func (t *Test) add() {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.count++
}
func (t *Test) reduce() {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.count--
}

2. 愉快的执行main函数测试

func main() {
	var t = &Test{}
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 0; i < 100000; i++ {
			t.add()
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 100000; i++ {
			t.reduce()
		}
	}()
	wg.Wait()
	fmt.Println(t.count)
}

3. 重头戏使用channel模拟锁

type Lock struct {
	ch chan struct{}
}

func (l *Lock) Lock() {
	l.ch <- struct{}{}
}
func (l *Lock) Unlock() {
	select {
	case <-l.ch:
	default:
		panic("不可重复解锁")
	}
}

4. 最后我们把Test结构体里面的mutex字段类型换成*Lock,完美perfect