每种变成语言都会需要处理并发,内存共享的问题,在java中,对多个线程对同一个内存区域的操作是通过建立内存屏障实现的.(- [ ]. 这里的专业名词是什么?准确度待验证). 而在golang中,虽然也提供了这种并发处理方式,(并发,内存共享,概念怎么界定)但是,golang更推荐的是CSP的思想,
Concurrency and multi-threaded programming have over time developed a reputation for difficulty. We believe this is due partly to complex designs such as pthreads and partly to overemphasis on low-level details such as mutexes, condition variables, and memory barriers. Higher-level interfaces enable much simpler code, even if there are still mutexes and such under the covers.
One of the most successful models for providing high-level linguistic support for concurrency comes from Hoare's Communicating Sequential Processes, or CSP. Occam and Erlang are two well known languages that stem from CSP. Go's concurrency primitives derive from a different part of the family tree whose main contribution is the powerful notion of channels as first class objects. Experience with several earlier languages has shown that the CSP model fits well into a procedural language framework.
这里的具体实现就是channel
- 具体使用示例 (https://golang.org/doc/faq#csp)
-
golang底层的实现 (https://draveness.me/golang/concurrency/golang-channel.html#微信公众号)
CHANNEL
channel提供了一种并发应用中,用于在发送方和接收方处理同一个变量的机制,channel的零值为nil <-箭头表示channel的方向,发送方or接收方,如果不指定方向,表示这个channel是双向的
使用 ch <- i 表达式向 Channel 发送数据时遇到的几种情况: 如果当前 Channel 的 recvq 上存在已经被阻塞的 Goroutine,那么会直接将数据发送给当前的 Goroutine 并将其设置成下一个运行的协程; 如果 Channel 存在缓冲区并且其中还有空闲的容量,我们就会直接将数据直接存储到当前缓冲区 sendx 所在的位置上; 如果都不满足上面的两种情况,就会创建一个 sudog 结构并加入 Channel 的 sendq 队列并更新到 Goroutine 的 waiting 字段上,同时当前的 Goroutine 就会陷入阻塞等待其他的协程向 Channel 接收数据,一旦有其它的协程向 Channel 接收数据时就会唤醒当前的 Goroutine; 发送数据的过程中包含几个会触发 Goroutine 调度的时机,首先是发送数据时发现 Channel 上存在等待接收数据的 Goroutine,这是会立刻设置处理器的 runnext 属性,但是并不会立刻触发调度,第二个时机是发送数据时并没有找到接收方并且缓冲区已经满了,这时就会将自己加入 Channel 的 sendq 队列并立刻调用 goparkunlock 触发 Goroutine 的调度让出处理器的使用权。
当我们向 Channel 发送消息并且 Channel 中存在处于等待状态的 Goroutine 协程时,就会执行以下的过程: 调用 sendDirect 函数将发送的消息拷贝到接收方持有的目标内存地址上; 将接收方 Goroutine 的状态修改成 Grunnable 并更新发送方所在处理器 P 的 runnext 属性,当处理器 P 再次发生调度时就会优先执行 runnext 中的协程;
FAQ
https://golang.org/doc/faq#csp