很多人喜欢 Go 语言,其实是因为Go语言有其独特的语言属性在支撑着其在编程语言界的发展,今天兄弟连Go语言+ 区块链培训 老师给大家介绍一下关于Go语言并发技术3:管道通信,下面我们一起来看一下吧。( http://bt.itxdl.cn/ )
channel 介绍
channel 提供了一种通信机制,通过它,一个 goroutine 可以想另一 goroutine 发送消息。channel 本身还需关联了一个类型,也就是 channel 可以发送数据的类型。例如: 发送 int 类型消息的 channel 写作 chan int 。
channel 创建
channel 使用内置的 make 函数创建,下面声明了一个 chan int 类型的 channel:
ch := make(chan int)
· 1
c和 map 类似,make 创建了一个底层数据结构的引用,当赋值或参数传递时,只是拷贝了一个 channel 引用,指向相同的 channel 对象。和其他引用类型一样,channel 的空值为 nil 。使用 == 可以对类型相同的 channel 进行比较,只有指向相同对象或同为 nil 时,才返回 true
channel 的读写操作
ch := make(chan int)
// write to channel
ch <- x
// read from channel
x <- ch
// another way to read
x = <- chnnel 一定要初始化后才能进行读写操作,否则会永久阻塞。
channel 一定要初始化后才能进行读写操作,否则会永久阻塞。
关闭 channel
golang 提供了内置的 close 函数对 channel 进行关闭操作。
ch := make(chan int)close(ch)
有关 channel 的关闭,你需要注意以下事项:
1. 关闭一个未初始化(nil) 的 channel 会产生 panic
2. 重复关闭同一个 channel 会产生 panic
3. 向一个已关闭的 channel 中发送消息会产生 panic
4. 从已关闭的 channel 读取消息不会产生 panic,且能读出 channel中还未被读取的消息,若消息均已读出,则会读到类型的零值。从一个已关闭的 channel 中读取消息永远不会阻塞,并且会返回一个为
5. false 的 ok-idiom,可以用它来判断 channel 是否关闭
6. 关闭 channel 会产生一个广播机制,所有向 channel 读取消息的 goroutine 都会收到消息
ch := make(chan int, 10)
ch <- 11
ch <- 12
close(ch)
forx := range ch {
fmt.Println(x)
}
x, ok := <- ch
fmt.Println(x, ok)
-----
output:
11
12
0 false
channel 的类型
channel 分为不带缓存的 channel 和带缓存的 channel。
无缓存的 channel
从无缓存的 channel 中读取消息会阻塞,直到有 goroutine 向该 channel 中发送消息;同理,向无缓存的 channel 中发送消息也会阻塞,直到有 goroutine 从 channel 中读取消息。
通过无缓存的 channel 进行通信时,接收者收到数据 happens before 发送者 goroutine 唤醒
有缓存的 channel
有缓存的 channel 的声明方式为指定 make 函数的第二个参数,该参数为 channel 缓存的容量
ch := make(chan int, 10)
· 1
有缓存的 channel 类似一个阻塞队列(采用环形数组实现)。当缓存未满时,向 channel 中发送消息时不会阻塞,当缓存满时,发送操作将被阻塞,直到有其他 goroutine 从中读取消息;相应的,当 channel 中消息不为空时,读取消息不会出现阻塞,当 channel 为空时,读取操作会造成阻塞,直到有 goroutine 向 channel 中写入消息。
ch := make(chan int, 3)
// blocked, read from empty buffered channel
<- ch
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
// blocked, send to full buffered channel
ch <- 4
通过 len 函数可以获得 chan 中的元素个数,通过 cap 函数可以得到 channel 的缓存长度。
实例
通过channel实现同步
导入依赖
import (
"fmt"
"time"
)
//语法点①:创建int类型的无缓存管道//var ch = make(chan int)varch = make(chan int,0)
funcPrinter(str string) {
for_, data := range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
fmt.Printf("\n")
}
func person1() {
//打印完需要7秒钟
//劳资不打印完是不会往管道中塞数据的,阻塞不死你丫的
Printer("今生注定我爱你")
//箭头指向管道内部,写数据
//在打完今生注定我爱你(耗时7秒钟)后,才写入数据
//语法点②:向管道里写数据,无论读写,箭头只能朝左
//语法点⑤:如果管道缓存已满,则阻塞等待至有人取出数据腾出空间,再写入
ch <- 666
}
func person2() {
//箭头指向管道外面,代表从管道中拿出数据,读数据
//语法点③:从管理取出数据,但不不接收
//语法点⑥:管道里没数据时,阻塞死等
<-ch
//语法点④:从管理取出数据,且使用data变量接收
//data:=<-ch
//fmt.Println("读出数据:",data)
//终于妈的可以打印了
Printer("FUCKOFF")
}
func main() {
go person1()
go person2()
//主协程赖着不死
for {
time.Sleep(time.Second)
}
}
通过channel实现同步和数据交互
package main
import (
"fmt"
"time"
)
func main() {
//创建无缓存管道
ch := make(chan string)
//5、主协程结束
defer fmt.Println("主协程也结束")
//子协程负责写数据
go func() {
//3、结束任务
defer fmt.Println("子协程调用完毕")
//1、缓缓打印2次序号
for i := 0; i < 2; i++ {
fmt.Println("子协程 i= ", i)
time.Sleep(time.Second)
}
//2、向管道发送数据
ch <- "我是子协程,工作完毕"
}()
//4、阻塞接收
str := <-ch
fmt.Println("str = ", str)
}
无缓冲的channel
package main
import (
"fmt"
"time"
)
func main() {
//创建一个无缓冲的管道
ch := make(chan int, 1)
//长度0,缓存能力0
fmt.Printf("len(ch) = %d, cap(ch)=%d\n", len(ch), cap(ch))
go func() {
//向管道中存入0,被阻塞,存入1,被阻塞,存入2
for i := 0; i < 3; i++ {
fmt.Println("子协程: i = ", i)
ch <- i
fmt.Println("5秒以内被打印出来给杰神100万!")
}
}()
//睡眠2秒
time.Sleep(5 * time.Second)
//读取0,被阻塞,读取1,被阻塞,读取2
for i := 0; i < 3; i++ {
num := <-ch
fmt.Println("num = ", num)
}
}
有缓存的channel
package main
import (
"fmt"
"time"
)
func main() {
//创建3缓存的管道
ch := make(chan int, 3)
//长度0,缓存能力3(即使没人读,也能写入3个值)
fmt.Printf("len(ch) = %d, cap(ch) = %d\n", len(ch), cap(ch))
//一次性存入3个:012,3456789
go func() {
for i := 0; i < 10; i++ {
ch <- i
fmt.Printf("子协程存入[%d]: len(ch) = %d, cap(ch) = %d\n", i, len(ch), cap(ch))
//time.Sleep(1 * time.Second)
}
}()
//time.Sleep(5 * time.Second)
//一次性读取3个:012,345,678,9
for i := 0; i < 10; i++ {
num := <-ch
fmt.Println("num = ", num)
}
time.Sleep(1*time.Nanosecond)
}
更多区块链视频教程/源码/课件/学习资料-企鹅QUN:591229276
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 区块链技术语言(二十七):Go语言并发编程(上)
- Java并发系列—并发编程基础
- [Java并发-17-并发设计模式] Immutability模式:如何利用不变性解决并发问题?
- JAVA并发编程之并发模拟工具
- Java并发系列—并发编程的挑战
- Core Java 并发:理解并发概念
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Form Design
Luke Wroblewski / Rosenfeld Media / 2008-5-2 / GBP 25.00
Forms make or break the most crucial online interactions: checkout, registration, and any task requiring information entry. In Web Form Design, Luke Wroblewski draws on original research, his consider......一起来看看 《Web Form Design》 这本书的介绍吧!
JSON 在线解析
在线 JSON 格式化工具
RGB转16进制工具
RGB HEX 互转工具