首页 文章 channel

channel

来源:https://blog.csdn.net/qq_52563729/article/details/126093532 发布时间:2022-03-28 14:44:14 作者:Soul-Yang 阅读量:263

1.为什么设计成线程安全?

      不同协程通过channel 通信,本身使用场景就是多线程,为了保证数据一致性,必须实现线程安全。

2.如何实现线程安全的?

      channel底层的实现中,hchan结构体中采用Mutex锁来保证数据读写安全,在对循环数组buf中的数据进行入队和出队的操作时,必须先获取互斥锁,才能操作channel数据。

3.nil、关闭的 channel、有数据的 channel,再进行读、写、关闭会怎么样?

   注意:以下所有情况都是在goroutine中;因为在主程序中没有阻塞一说,直接死锁

     channel的两种类型——有缓冲,无缓冲


无缓冲 有缓冲
创建方式 make(chan int) make(chan int ,  2)
发送阻塞 数据接收前发送阻塞
缓冲区满时发送阻塞
接受阻塞 数据发送前接收阻塞
缓冲区空时接收阻塞

         无缓冲

             时刻都是同步状态

             无缓冲chan必须有发送G/接收G的同时有接收G/发送G,否则就会阻塞, 报错:fatal error: all goroutines are asleep - deadlock!      

package main
 
import (
"fmt"
"time"
)
 
func loop(ch chan int) {
for {
select {
case i := <-ch:
fmt.Println("this is value of unbuffer channel", i)
}
}
}
func main() {
 
ch := make(chan int)
ch <- 1
go loop(ch)
time.Sleep(1 * time.Millisecond)
 
}

    但如果把ch <-放到go loop(ch)下面,程序就会正常运行

        有缓冲

package main
 
import (
"fmt"
"time"
)
 
func loop(ch chan int) {
for {
select {
case i := <-ch:
fmt.Println("this is value of unbuffer channel", i)
}
}
}
func main() {
 
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
ch <- 4
go loop(ch)
 
time.Sleep(1 * time.Millisecond)
 
}

     也会报错:fatal error: all goroutines are asleep - deadlock!      

      是因为channel的大小为3,而要往里面塞4个数据,所以会阻塞住

  解决方法:

      1.把channel的长度调大(不是很好的解决方案)

      2.把发送者ch<-1等代码移动到go loop(ch)下面,让channel实时消费就不会导致阻塞了


      channel 有三种模式:只写操作模式(单向通道)、只读操作模式(单向通道)、读写操作模式(单向通道)


写模式 读模式 读写模式
创建 make(chan<- int) make(<-chan int)
make(chan int)


      


      channel 有三种状态:未初始化、正常、关闭


未初始化 关闭 正常
关闭 panic panic 正常关闭
发送 永远阻塞导致死锁 panic
阻塞或成功发送
接收 永远阻塞导致死锁
缓冲区为空则为零值,否则可以继续读 阻塞或成功接收

  注意点:

      1.一个channel不能多次关闭或导致panic。

      2.如果多个goroutine都监听同一个channel,那么channel上的数据都可以随机被任何一个goroutine取走进行消费。

      3.如果多个goroutine都监听同一个channel,那么这个channel被关闭,则所有goroutine都能收到退出信号。

注意:以上所有情况都是在goroutine中;因为在主程序中没有阻塞一说,会直接死锁


  
留言
https://blog.key9.cn/
用户登录
您还没有写任何评论内容!
您已经评论过了!
只能赞一次哦!
您已经收藏啦!