缓冲信道

语法结构:cap为容量

ch := make(chan type, cap)
  • 缓冲信道支持len()和cap()。
  • 只能向缓冲信道发送容量以内的数据。
  • 只能接收缓冲信道长度以内的数据。
  • 缓冲信道的容量是指信道可以存储的值的数量。我们在使用 make 函数创建缓冲信道的时候会指定容量大小。
  • 缓冲信道的长度是指信道中当前排队的元素个数。

信道是异步的,是一种在被创建时就被开辟了能存储一个或者多个值的信道。
这种类型并不要求发送与接收同时进行。只要缓冲区有未使用空间用于发送数据,或还包含可以接收的数据,那么其通信就会无阻塞地进行。只有在通道中没有要接收的值时,接收动作才会阻塞。

示例一

package main
import (
"fmt"
)
func main() {
//创建一个容量为3的缓冲信道
ch := make(chan string, 3)
ch <- "naveen"
ch <- "paul"
fmt.Println("capacity is", cap(ch)) //capacity is 3
fmt.Println("length is", len(ch)) //length is 2
fmt.Println("read value", <-ch) //read value naveen
fmt.Println("new length is", len(ch)) //new length is 1
}

   

示例二

package main
import (
"fmt"
"time"
)
func write(ch chan int) {
for i := 0; i < 5; i++ {
ch <- i
fmt.Println("successfully wrote", i, "to ch")
}
close(ch)
} func main() {
ch := make(chan int, 2)
go write(ch)
time.Sleep(2 * time.Second)
for v := range ch {
fmt.Println("read value", v,"from ch")
time.Sleep(2 * time.Second)
}
} 

创建一个两个容量的信道。
write协程先向信道里写入两个数据,然后阻塞,并打印,主协程睡眠两秒。
两秒后,主协程从信道中读取一个数据,并睡眠两秒,此时write协程继续向信道里写入一个数据,然后阻塞,等待主协程两秒后读取数据。

死锁

package main
import (
"fmt"
)
func main() {
ch := make(chan string, 2)
ch <- "naveen"
ch <- "paul"
ch <- "steve"
fmt.Println(<-ch)
fmt.Println(<-ch)
}

当我们向信道写入数据时,超出了信道的容量,因此写入发生了阻塞。现在想要写操作能够进行下去,必须要有其它协程来读取这个信道的数据。
但在程序中,并没有并发协程来读取这个信道,因此这里会发生死锁(deadlock)。

WaitGroup

假设我们有 3 个并发执行的 Go 协程(由Go 主协程生成)。Go 主协程需要等待这 3 个协程执行结束后,才会终止。这就可以用 WaitGroup 来实现。

package main

import (
"fmt"
"sync"
"time"
) func process(i int, wg *sync.WaitGroup) {
fmt.Println("started Goroutine ", i)
time.Sleep(2 * time.Second)
fmt.Printf("Goroutine %d ended\n", i)
//Done方法减少WaitGroup计数器的值,应在线程的最后执行。
wg.Done()
} /*
WaitGroup用于等待一组线程的结束。
父线程调用Add方法来设定应等待的线程的数量。
每个被等待的线程在结束时应调用Done方法。
同时,主线程里可以调用Wait方法阻塞至所有线程结束。
*/
func main() {
no := 3
var wg sync.WaitGroup
//并发协程
for i := 0; i < no; i++ {
/*
Add方法向内部计数加上delta,delta可以是负数;
如果内部计数器变为0,Wait方法阻塞等待的所有线程都会释放,
如果计数器小于0,方法panic。
*/
wg.Add(1)
go process(i, &wg)
}
//Wait方法阻塞直到WaitGroup计数器减为0。
wg.Wait()
fmt.Println("over")
}

 

最新文章

  1. this和super的区别
  2. C# Winform实现炫酷的透明动画界面
  3. Java 中的构造方法
  4. Codeforces Gym 100203G G - Good elements 暴力
  5. sqlserver 2012 重启是 ID 自动增长 1000的问题
  6. oracle 命令创建用户 、授权、数据库导入、导出
  7. JavaScript中常用的Document了解
  8. Games on a CD
  9. loadrunner controller:设置多个load generator
  10. NYOJ-63 小猴子下落(二叉树及优化算法详解)
  11. Android For JNI(一)——JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序,使用C启动JAVA程序
  12. Golang常见误区(二)
  13. RGB与HSB之间转换
  14. 2、每日复习点--ConcurrentHashMap vs HashMap vs LinkedHashMap vs HashTable
  15. 利用批处理文件删除系统托盘上的图标(适用于Windows各个版本)
  16. apache分割数组和集合的分法
  17. to do list_hadoop
  18. C语言转义字符&#39;\&#39;
  19. POJ 2398 - Toy Storage - [计算几何基础题][同POJ2318]
  20. 2879. [NOI2012]美食节【费用流】

热门文章

  1. java-mybaits-013-mybatis-Interceptor-拦截器执行顺序
  2. 123457123456#0#-----com.yuming.FromPuzzleGame01--前拼后广--宝宝农场拼图cym
  3. 123457123456#0#-----com.threeapp.headsoccer----宝宝头球大战
  4. SpringCloud学习成长之 九 服务链路跟踪
  5. (二)UML之类图、接口、包
  6. 树形DP入门学习
  7. JMETER安装教程
  8. GraphQL学习之原理篇
  9. 【ARM-Linux开发】TI 关于Gstreamer使用的几个参考
  10. Node中导入模块require和import??