package learnChannel
import (
"fmt"
"sync"
)
/*
单纯让函数并发是没有意义的,函数与函数之间需要交换数据才能体现函数并发的意义
虽然可以使用共享内存进行数据交换,但共享内存在不同的goroutine中容易发生竞态问题(资源竞争),为了保证数据交换的正确性
必须使用互斥锁进行枷锁,但这样做会造成资源的浪费
Go语言的并发模型是CSP 提倡通过通信共享内存而不是通过共享内存实现通信
如果说goroutine是Go程序的并发执行体,channel就是他们的连接,channel是可以让一个goroutine发生特定值到另一个goroutine的通信机制
Go语言中的通道是一种特殊类型,像一个传送带或者队列,总是遵循先入先出的规则,保证收发数据的顺序
每一个通道都是一个具体类型的导管,声明channel的时候需要为其指定元素类
var 变量 chan 元素类型
*/
var _ []int
var b chan int // 需要指定通道中元素的类型 他是一个引用类型,需要初始化才能使用
var wg sync.WaitGroup
func NoBuffChannel(){
//wg.Add(1)
fmt.Println(b)
b = make(chan int,2) //初始化一个带缓冲区的通道
//go func() {
// defer wg.Done()
// res := <-b
// fmt.Println(res)
//}()
fmt.Println("数值发送到通道里面了")
b <- 10 // 带缓冲区不会导致死锁
b <- 20
x := <- b
fmt.Println(b)
fmt.Println(x)
x = <- b
fmt.Println(x)
close(b)
//wg.Wait()
}
/*
<-
发送: ch1 <- 1 把1放到通道里面
接收: res := <- ch1 把通道1里面的数赋值给res
关闭: close
*/
func action(){
wg.Add(1)
fmt.Println(b)
b = make(chan int) // 初始化一个不带缓冲区的通道 这会导致没办法接收对方的信息
//b = make(chan int,100) //初始化一个带缓冲区的通道
go func() {
defer wg.Done()
res := <-b
fmt.Println(res)
}()
fmt.Println("数值发送到通道里面了")
b <- 10 // all goroutines are asleep - deadlock! 因为没有缓冲区接受所以导致死锁了
fmt.Println(b)
wg.Wait()
}
package learnChannel
import (
"fmt"
"sync"
)
//如果对一个已关闭的通道取值是可以的,只不过返回的OK是一个false 取值是通道类型的0值
var once sync.Once
func f1(ch1 chan int){
// 开启goroutine 将0~100的数据塞去channel中
defer wg.Done()
for i:=0;i<100;i++{
ch1 <- i
}
close(ch1)
}
func f2(ch1,ch2 chan int){
defer wg.Done()
// 开启goroutine从ch1中接受值,并将该值的平方发送到ch2中 这里有可能ch1里面没有值
for {
x,ok := <- ch1
if !ok{
break
}
ch2 <- x*x
}
//确保某个操作只执行一次 原子的操作
once.Do(func() {close(ch2)})
}
func Excel_channel(){
ch1 := make(chan int,50)
ch2 := make(chan int,100)
wg.Add(3)
go f1(ch1)
go f2(ch1,ch2)
go f2(ch1,ch2)
wg.Wait()
for ret := range ch2{
fmt.Println(ret)
}
}
package learnChannel
import "time"
/*
单向通道 一般用于参数,代表某个通道只能取值或者塞入
*/
// 代表只能塞入
func LearnSingalChannel(ch1 chan <- int){
time.Tick(time.Second) // 定时器
}
//代表只能获取
func LearnSingalChannel2(ch2 <- chan int){
}
channel | nil | 非空 | 空的 | 满了 | 没满 |
接收 | 阻塞 | 接收成功 | 阻塞 | 接收值 | 接受值 |
发送 | 阻塞 | 发送值 | 发送值 | 阻塞 | 发送值 |
关闭 | panic | 关闭成功,读取完数据后返回0值 | 关闭成功,返回0值 | 关闭成功读完数据后返回0值 | 关闭成功读完数据后返回0值 |