1. 程式人生 > >Golang從入門到精通(十九):Golang併發程式設計之Channel

Golang從入門到精通(十九):Golang併發程式設計之Channel

Go語言併發模型

Go 語言中使用了CSP模型來進行執行緒通訊,準確說,是輕量級執行緒goroutine之間的通訊。CSP模型和Actor模型類似,也是由獨立的,併發執行的實體所構成,實體之間也是通過傳送訊息進行通訊的。

Actor模型和CSP模型區別

Actor之間直接通訊,而CSP是通過Channel通訊,在耦合度上兩者是有區別的,後者更加鬆耦合。

主要的區別在於:CSP模型中訊息的傳送者和接收者之間通過Channel鬆耦合,傳送者不知道自己訊息被哪個接收者消費了,接收者也不知道是哪個傳送者傳送的訊息。在Actor模型中,由於Actor可以根據自己的狀態選擇處理哪個傳入訊息,自主性可控性更好些。

在Go語言中為了不堵塞程序,程式設計師必須檢查不同的傳入訊息,以便預見確保正確的順序。CSP好處是Channel不需要緩衝訊息,而Actor理論上需要一個無限大小的郵箱作為訊息緩衝。

CSP模型的訊息傳送方只能在接收方準備好接收訊息時才能傳送訊息。相反,Actor模型中的訊息傳遞是非同步 的,即訊息的傳送和接收無需在同一時間進行,傳送方可以在接收方準備好接收訊息前將訊息傳送出去。

Go語言Channel詳解

Channel定義

Go 語言中Channel型別的定義格式如下:

ChannelType = ( "chan" | "chan" "<-" | "<-" "chan"
) ElementType .

它包括三種類型的定義。可選的<-代表channel的方向。如果沒有指定方向,那麼Channel就是雙向的,既可以接收資料,也可以傳送資料。

chan T          // 可以接收和傳送型別為 T 的資料
chan <- float64  // 只可以用來發送 float64 型別的資料
<-chan int      // 只可以用來接收 int 型別的資料

注意:<- 總是優先和最左邊的型別結合(The <- operator associates with the leftmost chan possible)。

預設情況下,channel傳送方和接收方會一直阻塞直到對方準備好傳送或者接收,這就使得Go語言無需加鎖或者其他條件,天然支援了併發。

c := make(chan bool) //建立一個無緩衝的bool型Channel
c <- x        //向一個Channel傳送一個值
<- c          //從一個Channel中接收一個值
x = <- c      //從Channel c接收一個值並將其儲存到x中
x, ok = <- c  //從Channel接收一個值,如果channel關閉了或沒有資料,那麼ok將被置為false

使用 make 初始化Channel,還可以設定容量:

make(chan int, 100) #//建立一個有緩衝的int型Channel

Channel緩衝介紹

容量(capacity)代表Channel容納的最多的元素的數量,代表Channel的緩衝的大小。 如果沒有設定容量,或者容量設定為0, 說明Channel沒有緩衝。

在實際開發中,你可以在多個goroutine從/往一個channel 中 receive/send 資料, 不必考慮額外的同步措施。

Channel可以作為一個先入先出(FIFO)的佇列,接收的資料和傳送的資料的順序是一致的。

不帶緩衝的Channel兼具通訊和同步兩種特性,在併發開發中頗受青睞。例如:

// _Channels_ are the pipes that connect concurrent
// goroutines. You can send values into channels from one
// goroutine and receive those values into another
// goroutine.

package main

import "fmt"

func main() {

    // Create a new channel with `make(chan val-type)`.
    // Channels are typed by the values they convey.
    messages := make(chan string)

    // _Send_ a value into a channel using the `channel <-`
    // syntax. Here we send `"ping"`  to the `messages`
    // channel we made above, from a new goroutine.
    go func() { messages <- "ping" }()

    // The `<-channel` syntax _receives_ a value from the
    // channel. Here we'll receive the `"ping"` message
    // we sent above and print it out.
    msg := <-messages
    fmt.Println(msg)
}

上面示例的程式中,我們建立了一個不帶緩衝的string型別Channel,然後在一個goroutine把“ping”用channel<-傳遞給了這個Channel。<-channel收到了這個值,然後在main函式打印出來。

其實在這裡我們利用Channel悄然把“ping”message從一個goroutine轉移到了main goroutine,實現了執行緒間(準確的說,goroutine之間的)通訊。 因為channel傳送方和接收方會一直阻塞直到對方準備好傳送或者接收,這就使得我們在程式末尾等”ping” message而無需其他的同步操作。

相關推薦

Golang入門精通Golang併發程式設計Channel

Go語言併發模型 Go 語言中使用了CSP模型來進行執行緒通訊,準確說,是輕量級執行緒goroutine之間的通訊。CSP模型和Actor模型類似,也是由獨立的,併發執行的實體所構成,實體之間也是通過傳送訊息進行通訊的。 Actor模型和CSP模型區別 A

Golang入門精通Golang併發程式設計Goroutine

程序,執行緒,並行和併發 一個應用程式是執行在機器上的一個程序;程序是一個執行在自己記憶體地址空間裡的獨立執行體。一個程序由一個或多個作業系統執行緒組成,這些執行緒其實是共享同一個記憶體地址空間的一起工作的執行體。幾乎所有’正式’的程式都是多執行緒的,以便讓使

Golang入門精通Golang方法

方法 在 Go 語言中有一個概念和函式極其相似,叫做方法 。Go 語言的方法其實是作用在接收者(receiver)上的一個函式,接收者是某種非內建型別的變數。因此方法是一種特殊型別的函式。 接收者型別可以是(幾乎)任何型別,不僅僅是結構體型別:任何型別都可以

Unity Shader入門精要筆記雙面渲染的透明效果

本系列文章由Aimar_Johnny編寫,歡迎轉載,轉載請標明出處,謝謝。 前面文章介紹了透明度測試和透明度混合,基本滿足了透明的效果需求,但嚴格來說,現實中透明除了能看到後面物體的樣子,也應該能看到透明物體內部的樣子,但前面的方法我們都看不到其內部結構,這是因為預

Spring Boot入門系列整合mybatis,使用註解實現動態Sql、引數傳遞等常用操作!

前面介紹了Spring Boot 整合mybatis 使用註解的方式實現資料庫操作,介紹瞭如何自動生成註解版的mapper 和pojo類。 接下來介紹使用mybatis 常用註解以及如何傳引數等資料庫操作中的常用操作。 其實,mybatis 註解方式 和 XML配置方式兩者的使用基本上相同,只有在構建 SQL

SpringSpring AOP切面的優先級

表達 對象 技術分享 方法 多個 getname exp 訪問 ioc容器 背景: 1)指定切面優先級示例:有的時候需要對一個方法指定多個切面,而這多個切面有時又需要按照不同順序執行,因此,切面執行優先級別指定功能就變得很實用。 2)重復使用切入點表達式:上一篇文章中,

java基礎學習總結Unsafe與CAS

Unsafe         簡單講一下這個類。Java無法直接訪問底層作業系統,而是通過本地(native)方法來訪問。不過儘管如此,JVM還是開了一個後門,JDK中有一個類Unsafe,它提供了硬體級別的原子操作。     &n

Spring Boot + Spring Cloud 實現許可權管理系統 後端篇服務消費Ribbon、Feign

技術背景 上一篇教程中,我們利用Consul註冊中心,實現了服務的註冊和發現功能,這一篇我們來聊聊服務的呼叫。單體應用中,程式碼可以直接依賴,在程式碼中直接呼叫即可,但在微服務架構是分散式架構,服務都執行在各自的程序之中,甚至部署在不同的主機和不同的地區。這個時候就需要相關的遠端呼叫技術了。 Spring

通證經濟大局觀使用者、時間、價值生產率

對於一個國家來說,居民大體是穩定的,且居民幾乎24小時都在為國家這個經濟體做貢獻,所以生產能力用人口數時間生產率來表示,是比較合適的。 但通證經濟體不同,比如某個DAPP的使用者註冊數有100萬,但有80萬註冊完後啥都沒幹,這種情況下,雖然這100萬都是使用者,但在衡量整個通證經濟體的價

搭建自己的部落格新增簡單的評論功能

因為評論可以作為一個模組,所以單獨建立一個app,專門用來處理評論。 1、變化的部分 2、上程式碼 {# 引用模板 #} {% extends 'base.html' %} {% load staticfiles %} {% block header_extends

演算法題二叉搜尋樹轉雙鏈表

題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 輸入輸出示例: {10,6,4,8,14,12,16} from left to right:4,6,8,10,12,14,16 from right

Java併發final實現原理 淺談Java中的final關鍵字

final在Java中是一個保留的關鍵字,可以宣告成員變數、方法、類以及本地變數。 一旦你將引用宣告作final,你將不能改變這個引用了,編譯器會檢查程式碼,如果你試圖將變數再次初始化的話,編譯器會報編譯錯誤。 一、final變數   final成員變量表示常量,只能被賦值一次,賦值後值不再改變(fin

機器學習筆記TensorFlow實戰多執行緒輸入資料

1 - 引言 為了加速模型訓練的時間,TensorFlow提供了一套多執行緒處理輸入資料的框架。 下面我們來詳細的介紹如何使用多執行緒來加速我們的模型訓練速度 2 - 佇列與多執行緒 在TensorFlow中,佇列和變數類似,我們可以修改它們的狀態。下面給出一個示例來展示如

linux系列firewall-cmd命令

1、命令格式   firewall-cmd [選項] [引數] 2、命令功能:   簡單來說是一個防火牆管理工具。 3、簡單使用: systemctl start firewalld # 啟動, systemctl enable firewalld # 開機啟動 systemctl sto

opencv學習Canny邊緣檢測

參考學習連結:https://www.cnblogs.com/mightycode/p/6394810.html 程式碼如下: #匯入cv模組 import cv2 as cv import numpy as np #Canny邊緣提取 def edge_demo(image):

大資料hive資料庫基本操作與表分類

一、建立資料庫 1.建立一個數據,資料庫在HDFS上的預設儲存路徑是/user/hive/warehouse/*.db create database db_hive; 2.避免建立的資料庫已經存在,增加if not exists create database 

Spring Security6. Security Namespace Configuration

6.1 Introduction Namespace configuration has been available since version 2.0 of the Spring Framework. It allows you to supplement the traditional Sp

javaweb學習筆記連線池

目錄 1.連線池概念 資料庫連線池(Connection pooling)是程式啟動時建立足夠的資料庫連線,並將這些連線組成一個連線池,由程式動態地對池中的連線進行申請,使用,釋放。 資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池

Linux小小白入門教程移動/複製命令

以下操作在Linux終端進行。Linux因為許可權非常嚴格,所以暫時所有的命令操作全部是在/home資料夾下的/yangjw資料夾下進行。/yangjw資料夾就是登入使用者名稱所在的資料夾,出了此資料

Linux小小白入門教程使用者和使用者組

Linux是一個許可權控制非常嚴格的作業系統。在不瞭解Linux許可權規則前提下,基本對Linux的操作會寸步難行。 簡介 Linux中許可權、使用者、使用者組三者之間關係緊密。要更好的使用Linu