【Duke】CSP并发机制 023 - PingPongGooo/GoFoundation GitHub Wiki

CSP 并发机制

Communicating sequential processes

依赖于一个通道完成 两个通信实体之间的协调

CSP vs. Actor
和 Actor 的直接通讯不同,CSP模式则是通过Channel 进行通讯的, 更松耦合一些。

Go中 channel 是有容量限制并且独立于处理Groutine, 而如 Erlang,Actor模式中的 mailbox容量是无限的,接收进程也总是被动地处理消息。


Go 语言中地 Channel机制有两种

1. 通讯地双方必须同时在channel上才能完成本次地交互。任何一方不在地时候,另外一方就会阻塞,等待。知道,两方都在时。才完成交互。
2. buffer channel   channel可以设置容量,容量在没有满地情况下,发送方可以放消息,当满了之后,发送方就需要等待,channel容量有空间,不然就会阻塞等待。 如果channel容量为空,接收消息地就会阻塞等待。
package csp

import (
	"fmt"
	"testing"
	"time"
)

func service() string{
	time.Sleep(time.Millisecond * 50) // 耗时操作
	return "Done"
}

func otherTask() {
	fmt.Println("working on something else")
	time.Sleep(time.Millisecond * 100)  // 延迟输出信息
	fmt.Println("Task is done")
}

func TestService(t *testing.T)  {
	fmt.Println(service())  // 串行
	otherTask()
}

串行输出 耗时 0.15s

=== RUN   TestService
Done
working on something else
Task is done
--- PASS: TestService (0.15s)
PASS
// 第一种 channel 通信双方阻塞等待
func AsyncService() chan string { // 返回 channel
	retCh := make(chan string)  // 声明一个channel 指明 channel类型,放入string,就只能放string
	go func() { // 1. 启动协程
		ret := service()
		fmt.Println("returned result")
		retCh <- ret // 把结果放回到channel中
		fmt.Println("service exited")
	}()
	return retCh
}

func TestAsyncService(t *testing.T){
	retCh := AsyncService() // 另外一个任务。 放到另外一个协程中执行。
	otherTask()
	fmt.Println(<-retCh)  // 当我们需要结果的时候,去channel中把数据读出来。
}
=== RUN   TestAsyncService
working on something else
returned result
Task is done
Done
service exited
--- PASS: TestAsyncService (0.10s)
PASS

// 第2种 channel buff 当前设置为 1
func AsyncService2() chan string { // 返回 channel
	retCh := make(chan string,1) // 声明一个channel 指明 channel类型,放入string,就只能放string  //
	go func() { // 1. 启动协程
		ret := service()
		fmt.Println("returned result")
		retCh <- ret // 把结果放回到channel中
		fmt.Println("service exited")
	}()
	return retCh
}

func TestAsyncService2(t *testing.T){
	retCh := AsyncService2() // 另外一个任务。 放到另外一个协程中执行。
	otherTask()
	fmt.Println(<-retCh)  // 当我们需要结果的时候,去channel中把数据读出来。
}
=== RUN   TestAsyncService2
working on something else
returned result
service exited
Task is done
Done
--- PASS: TestAsyncService2 (0.10s)
PASS