day03-go channal

https://mp.weixin.qq.com/s/90Evbi5F5sA1IM5Ya5Tp8w

不要通过共享内存来通信,而要通过通信来实现内存共享

并发哲学:它依赖 CSP 模型,基于 channel 实现

1.CSP

CSP 全称是 “Communicating Sequential Processes”, 被认为是 Go 在并发编程上成功的关键因素,大多数的编程语言的并发编程模型是基于线程和内存同步访问控制,Go 的并发编程的模型则用 goroutine 和 channel 来替代,书中提到:processes 被认为是需要输入驱动,并且产生输出,供其他 processes 消费,processes 可以是进程、线程、甚至是代码块   ----划重点


2.channal(先进先出,能影响goroutine的阻塞和唤醒)

Goroutine 用于执行并发任务,channel 用于 goroutine 之间的同步、通信、事件通知。

选择sync底层并发还是选择channel

channel是Go的第一对象,通过channel go实现了内存的共享,而且是多个goroutine同步和数据传递的重要手段


3.channel实现原理

channel底层结构

同步模式(无缓冲)下,必须要使发送方和接收方配对,操作才会成功,否则会被阻塞;异步模式(带缓冲)下,缓冲槽要有剩余容量,操作才会成功,否则也会被阻塞

创建一个容量大小为6,类型为int的带缓冲channel

一个内核线程管理多个goroutine.内核线程可以调度其他的 goroutine 来运行,内核线程本身不会阻塞。这就是通常我们说的 M:N模型,M:N模型有M,P,G构成,M是内核线程,代表运行goroutine,P为调度相关的context,保存了goroutine可运行的上下文,以及可运行的goroutine列表,G则是待运行的goroutine ,每个M都有一个P,

为何说channel是安全的:当sender向channel中发送第一条数据时,对buf加锁,然后将数据拷贝到buf中,增加sendx得值,释放该锁,然后receiver进行消费,加锁,将该buf中的数据拷贝出来,增加recvx得值,释放锁,他并没有做到共享锁,而是通过这个结构体,将内存的值进行拷贝的方式进行通信

channel接收发送数据的本质 :Remember all transfer of value on the go channels happens with the copy of value.

channal happen-before:

(1 第 n 个send一定happened before第 n 个receive finished,无论是缓冲型还是非缓冲型的 channel。

(2 对于容量为 m 的缓冲型 channel,第 n 个receive一定happened before第 n+m 个send finished。

(3 对于非缓冲型的 channel,第 n 个receive一定happened before第 n 个send finished。

(4 channel close 一定happened beforereceiver 得到通知。


4.如何优雅的关闭channel

don't close a channel from the receiver side and don't close a channel if the channel has multiple concurrent senders

(1 使用 defer-recover 机制,放心大胆地关闭 channel 或者向 channel 发送数据。即使发生了 panic,有 defer-recover 在兜底。

(2 使用 sync.Once 来保证只关闭一次。-----这个是我经常使用的关闭方法

根据 sender 和 receiver 的个数,分下面几种情况:

(1 一个 sender,一个 receiver            ---一个sender,从 sender 端关闭

(2 一个 sender, M 个 receiver           ---一个sender,从 sender 端关闭

(3 N 个 sender,一个 reciver              ---多个sender,可以在一个reciever端发送一个停止的信号

多个sender和一个reciever

(4 N 个 sender, M 个 receiver         ---增加中间人,代码请看原文

有缓冲的channel在关闭后仍能读出数据(v,ok := <- ch),当ok 为false时代表数据读完


5.channel的应用

(1 停止信号,同上面的关闭channel一样,作出停止的信号

(2 与timer结合,做定时任务

(3 解耦生产方和消费方

(4 控制并发数

limit 放在 func 内部而不是外部,如果在外层,就是控制系统 goroutine 的数量,可能会阻塞 for 循环,影响业务逻辑。limit 其实和逻辑无关,只是性能调优,放在内层和外层的语义不太一样。

结合https://zhuanlan.zhihu.com/p/27917262一起看

你可能感兴趣的:(day03-go channal)