第五部分-并发编程模型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没有广泛的生产环境检验

posted @ 2021-06-23 16:01  SpecialSpeculator  阅读(540)  评论(0编辑  收藏  举报