併發,線程,協程:概念是不可能概念的,google去吧。或者點擊這裏,查看上一篇文章golang
名稱 | 特色 |
---|---|
管道/匿名管道(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)互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量能夠由一個線程釋放,另外一個線程獲得。緩存
基本上就是推薦使用channel,這個是最推薦的使用形式;網絡
還有就是使用sync.Mutex
互斥鎖進行加鎖通信;多線程
更詳細的介紹之後寫;併發
這種狀況下,通常是不一樣『數據集合』須要進行『處理』,在處理的過程當中兩個數據集合對『結果』形成的影響沒有時序行;異步
這種狀況下,徹底能夠採用兩個數據單獨進行協程處理而後再進行後續運算;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
通常有些業務處理之後,有些『額外工做』須要處理可是不耽誤主協程返回數據,這個時候就能夠開個協程去作,不用等待post
// 僞代碼 result, err := processMethod() if err != nil { ..... } // 須要對結果進行寫緩存等其餘操做,不耽誤數據返回 go func() { err = saveRedis(result) if err != nil { ..... } } return result
例如,經過管道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!") } }