本文是在上一篇文章的基礎上Golang之併發編程一的基礎上的續篇,若是有興趣的話,你們能夠先看看上一篇的內容,也但願能給出建議,謝謝。php
好了,那接下來繼續說Golang的併發編程吧。html
在說到Golang的並行化時,先看看並行和併發分別是什麼吧。golang
併發:是在單核cpu的基礎上,線程經過時間片或者爭奪和讓出控制權來實現任務的切換,從而實現多個任務的執行。表面上看就好像多個任務在「同時」進行,而其實在某個時間點上,有且僅有一個任務在執行而已。編程
並行:是指多核的CPU能讓同一個進程內的線程,實現真正意義上的同時運行,在理想狀況下是不須要排隊的(實際是線程數量每每多餘cpu核數)。併發
在目前的Go編譯器中,還不可以發揮多核cpu的優點,雖然經過參加goroutine能夠實現多併發,簡化並行代碼的編寫,但這些goroutine都運行在同一個CPU核心上,在一個goroutine獲得時間片執行的時候,其餘goroutine都會處於等待狀態,因此有時候的實際效率可能並無單線程的高。.net
因此在目前的Golang版本中,咱們能夠經過設置環境變量來控制使用多少個CPU核心。線程
runtime.GOMAXPROCS(16)cdn
經過設置環境變量GOMAXPROCS的cpu核數,咱們能夠指定使用多少個cpu核心,另外,咱們能夠經過NumCPU()的方法,來獲取當前計算機的cpu核數。htm
runtime.NumCPU()blog
runtime.Gosched()
當調用這個方法後,該goroutine的會讓出本身的時間片讓其餘goroutine執行。
須要注意的還有一點:當一個goroutine發生阻塞,Go會自動地把與該goroutine處於同一系統線程的其餘goroutines轉移到另外一個系統線程上去,以使這些goroutines不阻塞
雖然使用了channel來做爲通訊手段,但仍是可能避免不了goroutine間的共享數據,因此在golang中,仍是提供了資源鎖的方案
Golang中提供了兩種鎖類型:sync.Mutex 、sync.RWMutex
Mutex:相似Java中的Lock,一個goroutine獲取鎖後其餘goroutine只可以等待,不管讀寫操做。
RWMutex:類型Java中的讀寫鎖,讀鎖佔用時,鎖寫操做,寫鎖佔用時,讀寫都鎖住。
對於全局中只須要運行一次的代碼,如初始化操做,golang提供了一個Once類型來保證惟一性操做
var once sync.Once
once.Do(方法名)
調用once.Do時,其餘goroutine會被阻塞,知道全局惟一的once.Do()調用結束後才繼續
示例:
var a string
var once sync.Once
func setup() {
a = "hello world"
}
func doprint() {
once.Do(setup)
print(a)
}
額外閱讀:golang線程同步WaitGroup
簡書:http://www.jianshu.com/p/76c8356a4338