当前位置: 首页 > news >正文

go并发学习笔记

包含了go学习笔记,含有channel的基础学习,编写数字的平方,如何成组的合并channel,如何优雅的关闭退出并发协程,通道阻塞情况分析,channel与哪些变成情况,可谓是收藏好文.

文章目录

  • 并发1:channel的基础学习
  • 并发2:编写数字的平方
  • 并发3:组装式编写数字的平方
  • 并发4:如何关闭退出并发协程
  • 并发5:通道阻塞情况
  • 并发5:channel情况汇总

并发1:channel的基础学习

func main() {
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2
	elem, ok := <-ch
	if ok != true {
		fmt.Println("channel closed")
	}
	fmt.Println(elem)
}

一个从channel里读,一个从channel里写

func main() {
	syncChan1 := make(chan struct{}, 1)
	syncChan2 := make(chan struct{}, 2)
	go func() {
		<-syncChan1
		fmt.Println("receive a sync signal and wait a second...[receiver]")
		time.Sleep(time.Second)
		for {
			if elem, ok := <-strChan; ok {
				fmt.Println("Received:", elem, "[receiver]")
			} else {
				break
			}
		}
		fmt.Println("stopped [receiver]")
		syncChan2 <- struct{}{}
	}()
	go func() {
		for _, elem := range []string{"a", "b", "c", "d"} {
			strChan <- elem
			fmt.Println("sent:", elem, "[sender]")
			if elem == "c" {
				syncChan1 <- struct{}{} //唤醒接收的go携程,
				fmt.Println("sent a sync signal:", elem, "[sender]")
			}
		}
		fmt.Println("ait 2 seconds...[sender]")
		time.Sleep(time.Second * 2)
		close(strChan)
		syncChan2 <- struct{}{}
	}()
	<-syncChan2
	<-syncChan2
}

赋值写入

type Counter struct {
	count int
}

var mapChan2 = make(chan map[string]*Counter, 1)

func (counter *Counter) String() string {
	return fmt.Sprintf("counter:%d", counter.count)
}
func main() {
	syncChan := make(chan struct{}, 2)
	go func() {
		for {
			if elem, ok := <-mapChan2; ok {
				counter := elem["count"]
				counter.count++
			} else {
				break
			}
		}
		fmt.Println("stopped [receiver]")
		syncChan <- struct{}{}
	}()
	go func() {
		countMap := map[string]*Counter{
			"count": &Counter{},
		}
		for i := 0; i < 5; i++ {
			mapChan2 <- countMap
			time.Sleep(time.Millisecond)
			fmt.Printf("The count map::%v [sender]\n", countMap)
		}
		close(mapChan2)
		syncChan <- struct{}{}
	}()
	<-syncChan
	<-syncChan
}

用struct进行通信

func main() {
	dataChan := make(chan int, 5)
	syncChan1 := make(chan struct{}, 1)
	syncChan2 := make(chan struct{}, 2)
	go func() {
		<-syncChan1
		for {
			if elem, ok := <-dataChan; ok {
				fmt.Printf("Received:%d [receiver]\n]", elem)
			} else {
				break
			}
		}
		fmt.Println("Done [receiver]")
		syncChan2 <- struct{}{}
	}()
	go func() {
		for i := 0; i < 5; i++ {
			dataChan <- i
			fmt.Printf("Sent:%d [sender]\n", i)
		}
		close(dataChan)
		syncChan1 <- struct{}{}
		syncChan2 <- struct{}{}
	}()
	<-syncChan2
	<-syncChan2
}

用select case进行读取

func main() {
	chanCap := 5
	intChan := make(chan int, chanCap)
	for i := 0; i < chanCap; i++ {
		select {
		case intChan <- 1:
		case intChan <- 2:
		case intChan <- 3:
		}
	}
	for i := 0; i < chanCap; i++ {
		fmt.Println(<-intChan)
	}
}

并发2:编写数字的平方

func producer(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		defer close(out)
		for _, n := range nums {
			out <- n
		}
	}()
	return out
}

func square(inCh <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		defer close(out)
		for n := range inCh {
			out <- n * n
		}
	}()
	return out

}

func main() {
	in := producer(1, 2, 3, 4, 5, 6)
	out := square(in)
	for ret := range out {
		fmt.Println(ret)
	}
	fmt.Println("done")
}

并发3:组装式编写数字的平方

func producer(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		defer close(out)
		for _, n := range nums {
			out <- n
		}
	}()
	return out
}

func square(inCh <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		defer close(out)
		for n := range inCh {
			out <- n * n
		}
	}()
	return out

}

func merge(cs ...<-chan int) <-chan int {
	out := make(chan int)
	var wg sync.WaitGroup
	collect := func(in <-chan int) {
		defer wg.Done()
		for n := range in {
			out <- n
		}
	}
	wg.Add(len(cs))
	for _, c := range cs {
		go collect(c)
	}
	go func() {
		wg.Wait()
		close(out)
	}()
	return out

}
func main() {
	in := producer(1, 2, 3, 4, 5, 6)
	c1 := square(in)
	c2 := square(in)
	c3 := square(in)
	for ret := range merge(c1, c2, c3) {
		fmt.Printf("%3d ", ret)
	}

	fmt.Println("\ndone")
}

并发4:如何关闭退出并发协程

文章链接:退出

  • 使用for-range退出
  • 使用,ok退出
  • 使用退出通道退出

并发5:通道阻塞情况

// 场景1
// 通道中无数据,但执行读通道

func ReadNoDataFromNoBufCh() {
	noBufCh := make(chan int)
	<-noBufCh //通道中没数据,你还读,必然阻塞
	fmt.Println("read from no buffer channel success")

}

//场景2
//通道中无数据,向通道中写数据,但无协程读取

func WriteNoBufCh() {
	ch := make(chan int)
	ch <- 1 //通道中无数据,向通道写数据,但无协程读取
	fmt.Println("write to no buffer channel success")
}

//场景3
//通道的缓存中无数据但执行读通道

func ReaNoDataFromBufCh() {
	noBufCh := make(chan int, 1)
	<-noBufCh //通道中没数据,你还读,必然阻塞
	fmt.Println("ReaNoDataFromBufCh")

}

//场景4
//通道缓存已经占满,向通道写数据,但无协程读

func WriteBufChButFull() {
	ch := make(chan int, 1)
	ch <- 1
	ch <- 2 //通道缓存已经占满,向通道写数据,但无协程读
	fmt.Println("WriteBufChButFull")
}

并发5:channel情况汇总

场景原理用法
需要不断从channel读取数据时该方法,当channel关闭时,for循环自动退出,可以防止读取已经关闭的channelfor x := range ch {}
v,ok := <- ch + select操作判断channel是否关闭ok为true,读到数据,ok为false,没读到数据v,ok := <- ch + select
需要对多个通道进行同时处理,但只处理最先发生的channel时select 可以同时监视多个通道的情况,只处理未阻塞的case,当通道为nil时,对应的case永远为阻塞,无论读写,特殊关注:普通情况下,对nil的通道写操作是要panic的select
如果协程只读或只写双向通道变成单向通道单向通道只能只读或只写
异步有缓冲通道可供多个协程同时处理,在一定程度可提高并发性make(chan int,10)
需要超时控制的操作使用selecttime.After,看操作和定时哪个先返回,处理先完成的,就达到了超时控制的效果case <- time.After()
并不希望在channel的读写上浪费时间是为操作加上超时的扩展,这里的操是channel的读或写case <-time.After()
退出时,显示通道所有协程退出所有读ch协程都会收到close(ch)的信号使用close(ch)关闭所有下游协程
使用channel传递信号,而不是传递数据时没数据需要传递时,传递空struct使用chan struct{} 作为信号channel
使用channel传递结构体数据时channel本质上传递的是数据的拷贝,拷贝的数据越小传输效率越高,传递结构体指针,比传递结构体更高效使用channel传递结构体的指针而非结构体
用来获取结果channel可以用来传递变量,channel自身也是变量,可以传递自己使用channel传递channel

相关文章:

  • Java 大视界 -- 基于 Java 的大数据实时数据处理框架性能评测与选型建议(121)
  • 美杜莎:带多个解码头的简单LLM推理加速框架
  • 《打造视频同步字幕播放网页:从0到1的技术指南》
  • 软考中级_【软件设计师】知识点之【面向对象】
  • 线程的常见使用方法
  • 硬件基础(4):(2)认识ADC参考电压
  • 当服务器出现卡顿该怎么办?
  • MELON的难题
  • 09第三方库的使用
  • 关于无感方波启动预定位阶段
  • PAT乙级真题(2014·冬)
  • JavaWeb-mysql8版本安装
  • 【SpringBoot】统一功能处理
  • vite.config.js 是Vite 项目的配置文件,分析具体用法
  • 消息队列为什么会有消费组的概念,什么作用,以订单系统为例说明
  • Vue _总结
  • AutoAWQ - 易用的 4 位量化模型工具
  • 栈在数组、链表中的应用 ---- 十进制转二进制函数、十进制转八进制函数
  • 【音视频 | AAC】AAC编码库faac介绍、使用步骤、例子代码
  • 【AD】5-16 泪滴的添加
  • 奉贤宜昌网站建设/国内十大软件培训机构
  • 中国城乡住房建设厅网站首页/站长之家查询域名
  • 大庆免费网站建设/windows优化大师官方网站
  • wordpress网站 frp穿透/seo搜索引擎优化课后答案
  • 贵阳做网站方舟网络/企业qq多少钱一年
  • 惠州做棋牌网站建设哪家便宜/如何做网页链接