继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

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

洋溢1310659
关注TA
已关注
手记 26
粉丝 2
获赞 4

课程名称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去处理,但要注意真正执行者传值的控制。

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

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP