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

    原创:做时间的朋友
  • 相关阅读:
    webpack-bundle-analyzer使用
    HTTP1.0,HTTP1.1和HTTP2.0区别
    document.readyState
    async和defer
    页面生命周期
    key的理解
    解释型语言和编译型语言
    AMD/CMD/CommonJS与ES6 Module的区别
    vue的keep-alive原理
    数字钱包metaplex-foundation
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/14923156.html
Copyright © 2020-2023  润新知