Channel创建方式:

  var c1 chan [value type]

  c1 = make([channel type] [value type], [capacity])

 

  [value type] 定义的是 Channel 中所传输数据的类型。

  [channel type] 定义的是 Channel 的类型,其类型有以下三种:

    "chan" 可读可写 : chan int 则表示可读写 int 数据的 channel

    "chan<-" 仅可写 : chan<- float64 则表示仅可写64位 float 数据的 channel

    "<-chan" 仅可读 : <-chan int 则表示仅可读 int 数据的 channel

  [capacity] 是一个可选参数,其定义的是 channel 中的缓存区 (buffer)。

    如果不填则默认该 channel 没有缓冲区 (unbuffered)。

    对于没有缓冲区的 channel,消息的发送和收取必须能同时完成,否则会造成阻塞并提示死锁错误。

    

Channel死锁:对 channel 的发送和接收动作永远不会同时发生,从而阻塞造成死锁。

        fatal error: all goroutines are asleep - deadlock!

 

      避免死锁方式1:使用goroutine并发执行。

                 通过 go 语句定义发送操作的方程在另一个协程并发运行,chan读取没有数据时会阻塞等待,从而能够解决死锁

      避免死锁方式2:使用 buffer。

              为 channel 添加一个缓冲区(buffer),这样只要 buffer 没有用尽,阻塞就不会发生,死锁也不会发生。

      

      Example:chan.go

      同样的,在 select 控制结构中,如果两个 channel 都阻塞且没有 default 流程分支时,也将产生死锁(deadlock)。

       Example:select.go

 

不同于传统的多线程通过共享内存来通信,CSP讲究的是“以通信的方式来共享内存。

普通的线程并发模型,就是像Java、C++、或者Python,他们线程间通信都是通过共享内存的方式来进行的。

非常典型的方式就是,在访问共享数据(例如数组、Map、或者某个结构体或对象)的时候,通过锁来访问,因此,在很多时候,衍生出一种方便操作的数据结构,叫做“线程安全的数据结构”。

例如Java提供的包”java.util.concurrent”中的数据结构。Go中也实现了传统的线程并发模型。

Go的CSP并发模型,是通过 goroutine 和 channel 来实现的。