聊聊併發,進程通訊方式,go協程簡單應用場景

開篇提問

  1. 知道併發,並行,線程,協程概念嗎?或者知道大概含義嗎?
  2. 有線程爲何還要有協程?區別是什麼?
  3. 『進程』通訊方式知道幾種?有沒有超過3種?
  4. golang『協程』通訊方式推薦?
  5. 使用併發的目的是爲何?是能幫咱們解決什麼問題嗎?

概念

併發,線程,協程:概念是不可能概念的,google去吧。或者點擊這裏,查看上一篇文章golang

  • 並行:通常是指多個CPU實例或者多臺機器在『同一時刻』同時執行某個邏輯(方法)

『進程』通訊方式

名稱 特色
管道/匿名管道(pipe) 管道的實質是一個內核緩衝區
有名管道(FIFO) 先進先出(first in first out);
以有名管道的文件形式存在於文件系統中;
信號(Signal) 無需知道該進程的狀態;
阻塞進程;
異步通訊;
消息隊列(Message Queue) 放在內核中的消息鏈表;
容許一個或多個進程向它寫入與讀取消息;
克服了信號承載信息量少缺陷;
目前主要有兩種類型的消息隊列:POSIX消息隊列以及System V消息隊列,系統V消息隊列目前被大量使用;
共享內存(share memory) 使得多個進程能夠能夠直接讀寫同一塊內存空間,是最快的可用IPC形式;
因爲多個進程共享一段內存,所以須要依靠某種同步機制(如信號量)來達到進程間的同步及互斥;
信號量(semaphore) 信號量是一個計數器,用於多進程對共享數據的訪問,信號量的意圖在於進程間同步只能經過兩個標準原子操做:wait(semap) , signal(semap) ;進行訪問
信號量是非負整型變量
操做也被成爲PV原語(P來源於荷蘭語proberen"測試",V來源於荷蘭語verhogen"增長",P表示經過的意思,V表示釋放的意思)
套接字(socket) 套接字是支持TCP/IP的網絡通訊的基本操做單元
套接字的特性由3個屬性肯定,它們分別是:域、端口號、協議類型。

信號量與互斥量之間的區別:
(1)互斥量用於線程的互斥,信號量用於線程的同步。這是互斥量和信號量的根本區別,也就是互斥和同步之間的區別。
互斥:是指某一資源同時只容許一個訪問者對其進行訪問,具備惟一性和排它性。但互斥沒法限制訪問者對資源的訪問順序,即訪問是無序的。
同步:是指在互斥的基礎上(大多數狀況),經過其它機制實現訪問者對資源的有序訪問。
在大多數狀況下,同步已經實現了互斥,特別是全部寫入資源的狀況一定是互斥的。少數狀況是指能夠容許多個訪問者同時訪問資源
(2)互斥量值只能爲0/1,信號量值能夠爲非負整數。
也就是說,一個互斥量只能用於一個資源的互斥訪問,它不能實現多個資源的多線程互斥問題。信號量能夠實現多個同類資源的多線程互斥和同步。當信號量爲單值信號量是,也能夠完成一個資源的互斥訪問。
(3)互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量能夠由一個線程釋放,另外一個線程獲得。緩存

go協程通信使用

基本上就是推薦使用channel,這個是最推薦的使用形式;網絡

還有就是使用sync.Mutex互斥鎖進行加鎖通信;多線程

更詳細的介紹之後寫;併發

go使用協程一些應用場景,簡單舉例

  1. 進行互不相干的『循環』,須要等待結果計算

這種狀況下,通常是不一樣『數據集合』須要進行『處理』,在處理的過程當中兩個數據集合對『結果』形成的影響沒有時序行異步

這種狀況下,徹底能夠採用兩個數據單獨進行協程處理而後再進行後續運算;socket

// 僞代碼
var result, data1, data2 int32
done1 := make(chan bool)
done2 := make(chan bool)
// 第一個數據集合,須要求和
go func() {
    for _, val := range dataset1 {
        data1 += val
    }
    done1 <- true
}

// 第二個數據集合,須要求和
go func() {
    for _, val := range dataset2 {
        data2 += val
    }
    done2 <- true
}

// 等待協程完成運算
<-done1
<-done2

// 結果進行相加
result = data1 + data2
  1. 須要額外進其餘不相干的業務,不耽誤『主協程』的返回值,不等待

通常有些業務處理之後,有些『額外工做』須要處理可是不耽誤主協程返回數據,這個時候就能夠開個協程去作,不用等待post

// 僞代碼

result, err := processMethod()
if err != nil {
    .....
}
// 須要對結果進行寫緩存等其餘操做,不耽誤數據返回
go func() {
    err = saveRedis(result)
    if err != nil {
    	.....
	}
}

return result
  1. 對某些任務進行時間限制,『超時關閉』當前操做

例如,經過管道channel發送某些數據,若超時則自動放棄本次發送,關閉通道。測試

// 定義兩個有緩衝通道,容量分別爲1
c1 := make(chan string, 1) 
c2 := make(chan string, 1)

go func() {                     
    time.Sleep(time.Second * 1) // 隔1秒發送數據
    c1 <- "data1"        
}()

go func() {
    time.Sleep(time.Second * 6) // 隔6秒發送數據
    c2 <- "data2"             
}()

for i := 0; i < 2; i++ {    
    // 給通道建立容忍時間,若是5s內沒法讀寫,就即刻返回
    tm := time.NewTimer(time.Second * 5) 
    // 使用select來獲取這兩個通道的值,而後輸出
    select {
        case data1 := <-c1:          // 接收c1通道數據(消費數據)
        	fmt.Println(msg1)
        case data2 := <-c2:          // 接收c2通道數據(消費數據)
        	fmt.Println(msg2)
        case <-tm.C:
        	fmt.Println("timeout!")
    }
}

篇末提問

  1. 使用過協程嗎?知道協程與線程的區別嗎?
  2. 若是是單核CPU,開協程會有用嗎?
  3. 本文因爲沒有幫助你提高code能力?
  4. 進程通信方式有沒有一點點了解?
  5. 你會使用本文的協程案例提高運行速度嗎?
相關文章
相關標籤/搜索