第五部分-并发编程模型4:CSP模型,golang的主力军
1.golang
语言层面支持并发的编程语言,支持并发是golang的非常重要特性
golang支持的是协程,可以类比java中的线程,解决并发问题的难点就是(线程之间的协作)
2.golang如何解决多协程之间的协作问题呢
(1)共享内存方式通信
golang也像java一样提供了管程和原子类对协程进行同步控制
(2)消息传递方式通信
本质上是为了避免共享,golang这个方案是基于CSP(Communicating Sequential Process)模型实现,golang本身推荐的是这种模式
3.csp模型
Actor模型中actor之间就是不共享内存,采用消息传递方式。
golang的csp模型与actor非常相似。
golang中推荐的是以协程之间消息传递方式来通信。
范例,以4个协程一起计算,1到100亿的结果
4核cpu,用了4个子协程并行执行,这4个子协程分别计算[1,25亿],[25,50亿],[50,75亿],[75,100亿]
主协程中汇总4个子协程的计算结果
golang中推荐使用channel,channel可以理解为线程安全的ArrayBlockQueue
calc()方法的返回值是一个只能接收数据的channel ch,子协程把计算结果放到ch里,主协程从ch里取到计算结果
import (
"fmt"
"time"
)
func main(){
var result, i unit64
start := time.Now()
for i = 1; i <= 10000000000; i ++ {
result += i
}
elapsed := time.Since(start)
fmt.Printf("执行消耗时间为:",elapsed)
fmt.Printf(",result:",result)
// 4个协程共同执行累加操作
start = time.Now()
ch1 := calc(1, 2500000000)
ch2 := calc(2500000001, 5000000000)
ch3 := calc(5000000001, 7500000000)
ch4 := calc(7500000001, 10000000000)
// 汇总4个协程的累加结果
result = <-ch1 + <-ch2 + <-ch3 + <-ch4
// 统计计算耗时
elapsed = time.Since(start)
fmt.Printf("执行消耗的时间为:", elapsed)
fmt.Println(", result:", result)
}
// 在协程中异步执行累加操作,累加结果通过channel传递
func calc(from uint64, to uint64) <-chan uint64 {
// channel用于协程间的通信
ch := make(chan uint64)
// 在协程中执行累加操作
go func() {
result := from
for i := from + 1; i <= to; i++ {
result += i
}
// 将结果写入channel
ch <- result
}()
// 返回结果是用于通信的channel
return ch
}
4.csp模型与生产-消费模式
csp模型,类比生产者-消费者模式
channel 类比阻塞队列
channel 容量可以为0,可以大于0.容量为0的channel是无缓冲的channel,容量大于0的是称为有缓冲的channel
创建有容量为4的channel,创建4个生产者,4个消费者
// 创建一个容量为4的channel
ch := make(chan int, 4)
// 创建4个协程,作为生产者
for i := 0; i < 4; i++ {
go func() {
// 把数字7塞入队列中
ch <- 7
}()
}
// 创建4个协程,作为消费者
for i := 0; i < 4; i++ {
go func() {
// 从队列中区属数据赋值为o
o := <-ch
fmt.Println("received:", o)
}()
}
(<-)完成向channel发送数据的和读取数据的任务
golang中的channel支持双向传输的。
5.csp模型与actor模型区别
(1)actor模型中没有channel,actor模型中是mailbox和channel非常像
mailbox对于程序员是透明的,而且明确归属与其中一个actor,是actor中的内部机制
actor之间是可以直接通信的,不需要中介
csp模型中channel不一样,是可见的,传递的消息都直接发到channel中
(2)actor模型中,发消息是非阻塞的,而csp中是阻塞的,
channel是阻塞队列,队列已满,向channel发送数据,会导致发送消息的协程阻塞
(3)消息送达
actor模型不保证百分百送达
csp模型是保证消息百分百送达。(有死锁风险)
java中可以使用jcsp来执行csp模型,jcsp没有广泛的生产环境检验