为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第13天 go语言并发模式

标签:
Go

课程名称GO开发工程师

课程章节:6-5:传统同步机制;6-6/7:并发模式

课程讲师ccmouse

课程内容

  1. 传统同步机制
type atomicInt struct {
	value int
	lock  sync.Mutex // 互斥锁
}

func (a *atomicInt) increment() {
	fmt.Println("safe increment")
	// 采用匿名函数对某一块代码区进行保护
	// 这样defer只控制这个匿名函数,函数匿名退出即释放锁
	func() {
		a.lock.Lock()
		defer a.lock.Unlock()
		a.value++
	}()
}

func (a *atomicInt) get() int {
	a.lock.Lock()
	defer a.lock.Unlock()
	return int(a.value)
}
  1. 并发模式一:
    对每个参数里的chan 开一个go routine
// 将c1和c2生成的数据发给c, 外部从c里取数据,c1或c2谁先发过来就处理谁
func fanIn(c1 chan string, c2 chan string) chan string {
	c := make(chan string)
	go func() {
		for {
			c <- <-c1 // 将c1里的值发给c
		}
	}()
	go func() {
		for {
			c <- <-c2
		}
	}()
	return c
}
  1. 并发模式二:
    通过Select并发执行
func fanInSelect(c1 chan string, c2 chan string) chan string {
	c := make(chan string)
	// 只用一个go routine ,借助系统select能力实现对多个channel数据的等待接收
	go func() {
		for {
			select {
			case v := <-c1:
				c <- v
			case v := <-c2:
				c <- v
			}
		}
	}()
	return c
}
  1. 并发陷阱:
func fanInFor(chs ...chan string) chan string {
	c := make(chan string)

	// ch 全局只有一份
	for _, ch := range chs {
		// 这样做的结果,会陷入循环陷阱
		// 循环时创建go routine
		// 真正读取ch值时,ch值已经不是当初创建go routine时的ch了(异步)
		//go func() {
		//	for {
		//		c <- <-ch
		//	}
		//}()

		// 解决方案1:用一个变量接收
		//chCopy := ch
		//go func() {
		//	for {
		//		//c <- <-ch
		//		c <- <-chCopy
		//	}
		//}()
		// 解决方案2:传值
		go func(ch chan string) {
			for {
				c <- <-ch
			}
		}(ch)
	}
	return c
}

课程收获

 对于确定数量的并发,可以使用select,只需要开一个go routine
 不确定的可以使用for range对开多个go routine去处理,但要注意真正执行者传值的控制。

图片描述
图片描述
图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消