文章目录

  • 前言
  • CSP 特点
  • CSP代码 演示
    • 1. 正常流程的代码
    • 2. CSP 未设置buffer 代码
    • 3. 设置指定大小的channel buffer
  • 总结

前言

CSP 这个名词大家会比较陌生,但是说到future 熟悉C++ / JAVA 线程模型的伙伴可能就会很熟悉了, 通过future机制能够实现两个线程之间的数据交互,当然通过通用的mutex 和 condition_variable 也能够实现,但这一些机制的引入无形中会大大增加代码的复杂度。

举例一段C++代码:

#include <iostream>
#include <future>
#include <thread>int fib(int n)
{if (n < 3) return 1;else return fib(n-1) + fib(n-2);
}int main()
{std::future<int> f1 = std::async(std::launch::async, [](){return fib(20);});std::future<int> f2 = std::async(std::launch::async, [](){return fib(25);});std::cout << "waiting...\n";//主线程在该处阻塞,直到获取到f1,f2两个线程到合法的结果f1.wait();f2.wait();std::cout << "f1: " << f1.get() << '\n';std::cout << "f2: " << f2.get() << '\n';
}

可以看到通过future能够达到延迟获取线程执行结果,主线程和两个子线程之间通信的过程就像建立了一个管道,子线程在一端塞入数据,主线程在一端取数据,管道内没有数据,主线程可以选择等待,也可以选择返回。

相关c++ 的future机制介绍可以参考C++ 多线程编程:future异步访问类。

同样Go语言中也会有这样 支持协程之间便捷自由得数据交互的机制,也就是CSP

CSP 特点

  • CSP支持通过channel 进行通信,即channel 支持维护一定大小的buffer(有大小限制)用作消息的存储,两个通信协程只需要向channel中放入 或取出即可,无需等待
  • CSP 支持 无指定buffer大小的channel通信,即一个协程等待结果,另一个协程负责发送,只有结果被取出来 才能向channel中放入。
  • 异步返回,调用协程执行 者无需等待,即可返回

基本使用语法可以参考代码演示中的第2段和第3段代码。

CSP代码 演示

1. 正常流程的代码

package groutineimport ("fmt""testing""time"
)func service() string {time.Sleep(time.Millisecond * 50)return "Service is Done"
}func otherTask() {fmt.Println("do something else ")time.Sleep(time.Millisecond * 100)fmt.Println("Task is done")
}// 顺序执行
func TestService(t *testing.T) {fmt.Println(service())otherTask()
}

这里 直接就是函数的调用,执行也会按照函数的调用顺序来执行

=== RUN   TestService
Service is Done
do something else
Task is done
--- PASS: TestService (0.16s)

2. CSP 未设置buffer 代码

func service() string {time.Sleep(time.Millisecond * 50)return "Service is Done"
}func otherTask() {fmt.Println("do something else ")time.Sleep(time.Millisecond * 100)fmt.Println("Task is done")
}func AsyncService() chan string {rech := make(chan string) // 声明一个channelgo func() {ret := service()fmt.Println("resturned result")rech <- ret // 向 channel 中放数据fmt.Println("service exited")}()return rech // 返回channel
}func TestAsyncService(t *testing.T) {ret := AsyncService()otherTask()// 从channel中取数据,且会阻塞到ret内部有有效数据才返回fmt.Println(<-ret) // 假如后续还有代码执行,则channel不会阻塞,// 立即执行goroutine后续的代码,直到channle内部获取到了有效的数据才会打印// time.Sleep(time.Second * 1)
}

执行如下:

=== RUN   TestAsyncService
do something else # otherTask 函数
resturned result # AsyncService 函数
Task is done # otherTask 函数
Service is Done # Service函数, 从channel中取数据,# 此时service函数还在睡眠,并未返回结果,# 这里会阻塞,直到取到有效的Service 给channel返回结果
service exited # AsyncService 函数
--- PASS: TestAsyncService (1.11s)

假如测试 代码变更为:

func TestAsyncService(t *testing.T) {ret := AsyncService()otherTask()// 从channel中取数据,且会阻塞到ret内部有有效数据才返回fmt.Println(<-ret) // 假如后续还有代码执行,则channel不会阻塞,// 立即执行goroutine后续的代码,直到channle内部获取到了有效的数据才会打印time.Sleep(time.Second * 1)
}

后两行的输出则会发生变化:

=== RUN   TestAsyncService
do something else # otherTask 函数
resturned result # AsyncService 函数
Task is done # otherTask 函数
service exited # AsyncService 函数# go routine执行完毕,不会阻塞在channel的有效数据获取处
Service is Done # Service函数 后续执行完毕返回给channel,才会打印
--- PASS: TestAsyncService (1.11s)

3. 设置指定大小的channel buffer

func AsyncService() chan string {rech := make(chan string,1 ) // 声明一个channel,并指定其buffer大小为1go func() {ret := service()fmt.Println("resturned result")rech <- ret // 向 channel 中放数据fmt.Println("service exited")}()return rech // 返回channel
}func TestAsyncService(t *testing.T) {ret := AsyncService()otherTask()fmt.Println(<-ret) // 从channel中取数据,即使是最后一段逻辑,也不会阻塞go routine的执行
}

最后的输出如下:

=== RUN   TestAsyncService
do something else
resturned result
service exited
Task is done
Service is Done
--- PASS: TestAsyncService (0.10s)

可以看到有了buffer的channel 不会阻塞go routine的执行,后续有了有效数据,直接从channel中取就可以了。

总结

Go 的CSP并发机制比较烧脑,协程之间的数据通信 可以异步获取结果而不需要等待正常逻辑的完成。
建议大家将以上 代码本地多多调试一番,对于CSP机制和应用场景的理解会更加深刻一些。

Go 分布式学习利器(19)-- Go并发编程 之 CSP(communicating sequential processes) 机制相关推荐

  1. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  2. 学习笔记:Java 并发编程②_管程

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 配套资料: ...

  3. 学习笔记:Java 并发编程⑥_并发工具_JUC

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 配套资料: ...

  4. 学习笔记:Java 并发编程④_无锁

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 配套资料: ...

  5. java并发学习之六:JCSP(Java Communicating Sequential Processes)实践

    首先得描述下什么是JCSP:CSP是Communicating Sequential Processes的缩写 在ibm的developerworks 中国上学习java的并发编程时无意发现的,因为在 ...

  6. 学习笔记(19):Python网络编程并发编程-互斥锁

    立即学习:https://edu.csdn.net/course/play/24458/296430?utm_source=blogtoedu 1.互斥锁: 多进程间的内存是相互隔离的,因此其数据也是 ...

  7. Python学习-基础篇8 并发编程

    一 背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...

  8. Java并发编程(07):Fork/Join框架机制详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.Fork/Join框架 Java提供Fork/Join框架用于并行执行任务,核心的思想就是将一个大任务切分成多个小任务,然后汇总每个小任务 ...

  9. Go 分布式学习利器(17)-- Go并发编程之协程机制:Grountine 原理及使用

    文章目录 1. Thread VS Groutine 2. Groutine 调度原理 3. Groutine 示例代码 关于Go的底层实现还需要后续持续研究,文中如有一些原理描述有误,欢迎指证. 1 ...

最新文章

  1. 清华大学史作强副教授专访:用流形、偏微分方程揭秘人工智能
  2. Expo大作战(三十六)--expo sdk api之 ImagePicker,ImageManipulator,Camera
  3. 深入浅出理解索引结构
  4. 机器学习Tensorflow基于MNIST数据集识别自己的手写数字(读取和测试自己的模型)
  5. 如何使用libgdx编写一个简单的游戏(一)— 雏形
  6. 白月黑羽教python_白月黑羽Python在线教程
  7. js table的所有td 按行合并
  8. web基础学习(十四)CSS3多列布局
  9. 高清数字电视视频处理器画质增强技术简介
  10. 【python报错】Python词云库wordcloud不显示中文
  11. vue中遇到使用iframe出现的页面崩溃问题
  12. mac怎么搭建网站服务器,mac搭建本地服务器(示例代码)
  13. Excel字符函数(3):字符查找函数Find、Search
  14. Texture2D变Sprite
  15. 麒麟操作系统iso文件中的img文件的解压与压缩
  16. 寻找书籍,以及格式转换网站
  17. Oracle中的dual是什么
  18. linux中jdk环境配置,安装MySQL,配置Hadoop伪分布式,配置hive环境
  19. 非常经典的JAVA编程题(素数)
  20. OpenCv实时设置摄像头参数/获得摄像头参数值的方法论

热门文章

  1. [笔记]C#基础入门(八)——C#标识符的命名规则
  2. npm start 作用
  3. [YY题]HDOJ5288 OO’s Sequence
  4. 使用 Flash Builder 的 Apple iOS 开发过程
  5. openoj的一个小比赛(F题解题报告)poj3978(dp+素数筛选)
  6. 程序员的周末:纯野的一天
  7. shell与 .sh文件与 .bash文件
  8. 安装凤凰os_这些系统帮助我们实现了在PC上安装安卓系统!
  9. linux 6.7 nfs安装yum,centos7下NFS使用与配置
  10. java 证件识别_证件识别接口JAVA调用示例