communicating sequential processes (CSP)机制的提出非常古老(在1978年),它不同于erlang的actor model。go语言实现的CSP使用的通道会让消息的发送与接收更加解耦。

一、go语言的channel机制

1、阻塞式

channel.png

接收者与发送者必须都在才能完成消息的发送与接收,如果发送者不在,接收者就必须等待,如果接收者不在,发送者也必须等待

2、非阻塞式
buffer_channel.png

这种被称为buffer channel,是更加松耦合的实现方式,发送者与接收者各自独立,只要消息队列未满,发送者可以一直向channel中写入msg,只要消息队列不空,接收者可以一直从channel中取msg。

二、代码实现

串行执行

func service() string {
    time.Sleep(time.Millisecond * 50)
    return "Done"
}

func otherTask() {
    fmt.Println("working on sth else")
    time.Sleep(time.Millisecond * 100)
    fmt.Println("Task is done")
}

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

输出:

Done
working on sth else
Task is done

使用channel改造成CSP:

func AsyncService() chan string {
    retCh := make(chan string)
    go func() {
        ret := service()
        fmt.Println("return result")
        retCh <- ret
        fmt.Println("service exited")
    }()
    return retCh
}

func TestAsyncService(t *testing.T) {
    retCh := AsyncService()
    otherTask()
    fmt.Println(<-retCh)
    time.Sleep(time.Second * 1)
}

执行结果:

working on sth else
return result
Task is done Done
service exited

由于是阻塞式的,所以发送者一直等接收者取走msg之后才退出,所有最后才打印"service exited"

改造成非阻塞式的:

func AsyncService() chan string {
    retCh := make(chan string, 1)
    go func() {
        ret := service()
        fmt.Println("return result")
        retCh <- ret
        fmt.Println("service exited")
    }()
    return retCh
}

输出结果:

working on sth else
return result
service exited
Task is done
Done

发送者完成消息发送就退出了


关翔宇
10 声望3 粉丝

即使是一只蜗牛,不停努力的奔跑,也能到达目标


引用和评论

0 条评论