[go學習筆記]二12、CSP併發機制

CSP

Communcating sequential processes (CSP)git

CSP vs. Actor

  • 和 Actor 的直接通信不一樣, CSP 模式則是經過 Channel 進行通信的, 更鬆耦合一些。
  • Go 中 channel 是有容量限制而且獨立於處理Groutine,而如 Erlang, Actor 模式中的 mailbox 的容量是無限的,接收進程也老是被動地處理消息。

Channel

先看一段代碼github

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()
}
複製代碼

輸出shell

=== RUN   TestService
Done
working on something else
task is done.
--- PASS: TestService (0.15s)
PASS

Process finished with exit code 0
複製代碼

能夠看出上述打印結果是按照程序執行的順序 下邊是用 Channelui

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 AsyncService() chan string {
	retCh := make(chan string)
	go func() {
		ret := service()
		fmt.Println("returned 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)
}
複製代碼

輸出spa

=== RUN   TestAsyncService
working on something else
returned result.
task is done.
Done
service exited.
--- PASS: TestAsyncService (1.11s)
PASS

Process finished with exit code 0
複製代碼

使用了channel ,能夠看到 service exited. 消息打印在了最後,因此,即使咱們channel裏邊放進了消息,其餘的task沒有結束以前,service的那個協程都會被阻塞住,直到channel 消息被接收掉; 下邊使用buffer channelcode

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 AsyncService() chan string {
	//retCh := make(chan string)
	retCh := make(chan string,1)
	go func() {
		ret := service()
		fmt.Println("returned 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)
}
複製代碼

輸出協程

=== RUN   TestAsyncService
working on something else
returned result.
service exited.
task is done.
Done
--- PASS: TestAsyncService (1.11s)
PASS

Process finished with exit code 0
複製代碼

這個時候咱們能看到 Done 這個消息打印到了 service exited. 後邊,說明那個service 協程沒有被阻塞,執行完就釋放掉了, channel 裏的消息在 otherTask 執行完之後, 正確的打印了出來;進程

筆記出處 github.com/wenjianzhan…get

相關文章
相關標籤/搜索