golang併發

 

golang中提供了goroutine,即所謂的協程編程。這裏面有幾個概念須要區分一下 (by 魏加恩 本文地址http://www.cnblogs.com/weijiaen/p/3970856.html)html

1. 併發&並行c++

    簡單一句話,併發是n個事情同時發生,可是不是同時刻發生。that is, parallelism means one or more things happen at the same time, while concurrency alows things happen together in a specific time. 併發實際上是指程序的幾個邏輯流在一塊兒進行,可是,某個時刻也許只執行其中的某個邏輯流。這取決於cpu是否多核。咱們知道,一個cpu核在一個時間只能執行一個指令,可是多個核就能夠執行多個指令,即所謂的並行。因此,併發是並行的必要條件,不是充分條件。golang

2. 協程&線程編程

    golang的協程由多牛逼,能夠建立多少個就不去說了,爲何呢,由於goroutine的消耗低。成本低的事情天然容易作。網絡

  開啓一個進程的消耗是很高的,須要分配單獨的堆棧,爲每一個進程分配一個進程控制塊,供操做系統進行調度。併發

    開啓線程的消耗次之,須要分配單獨的棧,可是堆是共享的,因此須要本身保證堆變量的併發訪問問題競爭問題。(因此,不是操做系統忙就是碼農忙!)app

    開啓協程的消耗,沒有分配額外的堆棧,協程只是一段代碼的入口,當你執行go funcA的時耗,只是在原來的堆棧上爲funcA分配了必定的G結構。相似進程控制塊,保存相關的funcA須要用來調度的信息,而後立刻就跳過了該指令,繼續執行下一個指令,剛剛建立的G結構會在適當的時候被go的runtime調度器調度並執行。異步

 

 協程究竟是個什麼東西呢?spa

   其實協程就是一個內核線程上執行的一段代碼。能夠理解內核線程是一個實際幹活的苦力,golang調度的單位是p(Processor),掛在一個線程上,而後這個p上放着n個routine等着執行,每一時刻,這個線程要執行哪一個routine由調度器來進行調度,因此routine也是須要切換的。可是並不須要像進程切換那樣作那麼多事情,因此代價小不少。那麼,既然是內核線程,就必定有可能出現阻塞(文件IO,網絡IO等),當發生這種狀況時,整個P能夠移動到另一個線程(經過新增或者從線程池取出一個線程),而後繼續執行,因此,所謂的同步,其實在底層仍是異步的,該阻塞的時候仍是阻塞,只不過你趕忙不到而已(再說說回調,其實就是修改了棧上的return address的地址,實現了從funcA進去,再從funcB出來)。操作系統

 

 協程如何通訊?

   通訊的方式有不少,好比c++經常使用信號,通訊隊列等,c++最經常使用的就是利用共享內存來通訊,而golang則提倡利用通訊來共享內存。那麼怎麼理解這兩個概念呢?

   利用共享內存來通訊,通常就是指往隊列寫一個消息,而後其餘進程從隊列讀取,實現了進程之間的通訊,而golang則把通訊做爲一個手段,目的是實現同時對一個內存進行編輯,並在語言層面上提供了channel來支持。channel的概念跟通訊隊列相似,也有緩衝,阻塞等概念,並在語言層面實現了鎖,寫代碼的時候能夠更專一於業務邏輯,不須要考慮競爭的問題,固然,若是過多的routine嘗試從同一channel進行讀寫,因爲競爭的關係效率確定也會降低。

相關文章
相關標籤/搜索