Golang 共用記憶體

來源:互聯網
上載者:User

  Golang語言中,處理序間通訊除了使用channel,還可以使用共用記憶體,即sync包。

Q-1

package mainimport ("fmt""time")func main() {for i := 1; i < 6; i++ {go func(x int) {time.Sleep(time.Second)fmt.Println("第", x, "個子goroutine執行結束")}(i)}fmt.Println("主goroutine執行結束")}

  上面的代碼毫無疑問的只會輸出:“主goroutine執行結束”,而不會輸出子goroutine執行結束,這是因為,主協程一旦執行完畢,整個進程就會結束。

  

sync組等待

  sync包中常用的有三個方法:Add(num int) 、 Done()、 Wait()

  sync中會在內部維持一個類似於計數器的東西,通過Add方法來增加計數器的值,增加參數num;通過Done來減少計數器的值,一次只能減少1;Wait方法會使主協程阻塞,只有到內部計數器的值為0時,阻塞才會解開。

  用法如下:

package mainimport ("fmt""sync""time")func main() {var wg sync.WaitGroupfor i := 1; i < 6; i++ {wg.Add(1) //計數器加1go func(x int) {time.Sleep(time.Second)fmt.Println("第", x, "個子goroutine執行結束")wg.Done() //goroutine執行完畢,計數器減1}(i)}wg.Wait()  // 計數器不為0的時候,一直阻塞;計數器變為0的時候,阻塞解開fmt.Println("主goroutine執行結束")}

  注意:添加的計時器數量必須比減少計時器的數量要少,否則會引發死結。

  比如,將計數器值增加了10,但是只執行了9次計數器減少,剩餘一個計數器,計數器的值始終不為0,則主協程一直等待,形成死結。但是較少計數器的次數可以比計數器的值要大,可以提前結束主協程的阻塞。

  

Q-2

  請看下面一段代碼,嘗試在兩個迴圈中,各自使sum加1,執行1000次,乍一看,覺得結果是sum的最終結果是2000,但是真正執行之後,結果不是2000。

package mainimport ("fmt""sync")func main() {var wg sync.WaitGroupwg.Add(2)var sum int = 0go func() {for i := 0; i < 1000; i++ {sum++}wg.Done()}()go func() {for i := 0; i < 1000; i++ {sum++}wg.Done()}()wg.Wait()fmt.Println(sum)}

  

sync互斥鎖

  sync互斥鎖有兩個常用的方法,Lock()加鎖,Unlock()解鎖。使用Lock加鎖後,不能再進行加鎖,只有當對其進行Unlock解鎖之後,才能對其加鎖。這個很好理解。

  如果對一個未加鎖的資源進行解鎖,會引發panic異常。

  可以在一個goroutine中對一個資源加鎖,而在另外一個goroutine中對該資源進行解鎖。

  使用樣本如下:

package mainimport ("fmt""sync")func main() {var wg sync.WaitGroupvar mutex sync.Mutexwg.Add(2)var sum int = 0go func() {for i := 0; i < 1000; i++ {mutex.Lock() //上鎖sum++mutex.Unlock()//解鎖}wg.Done()}()go func() {for i := 0; i < 1000; i++ {mutex.Lock() //加鎖sum++mutex.Unlock() //解鎖}wg.Done()}()wg.Wait()fmt.Println(sum)}

  

sync讀寫互斥鎖(多讀單寫鎖)

  允許對同一資源進行同時讀,但是不能進行同時寫,也不能進行一邊讀,一邊寫。

  如果一個資源被加了寫鎖,那麼就不能再給他加其他鎖,包括寫鎖,只能等寫鎖解開後,才能繼續加其他鎖。如果一個資源被加了讀鎖,那麼,仍然可以給該資源加讀鎖,但是不能加寫鎖,必須等讀鎖釋放後,才能加寫鎖。

  sync.RWMutex有四個常用的方法:

    Lock()加寫鎖  、 Unlock()取消寫鎖 、 RLock()加讀鎖 、 RUnlock()釋放讀鎖

  使用樣本:

package mainimport ("fmt""sync""time")var rwMutex sync.RWMutex //定義一個讀寫互斥鎖//注意傳遞的組等待是指標形式func WriteData(wg *sync.WaitGroup, id int) {rwMutex.Lock() //加 寫鎖fmt.Println("增加第", id, "個寫鎖")for i := 0; i < 5; i++ {fmt.Println("進行寫操作")time.Sleep(time.Second)}fmt.Println("釋放第", id, "個寫鎖")rwMutex.Unlock() //釋放 寫鎖wg.Done()}func ReadData(wg *sync.WaitGroup, id int) {rwMutex.RLock() //加 讀鎖fmt.Println("增加第", id, "個讀鎖")for i := 0; i < 5; i++ {fmt.Println("進行讀操作")time.Sleep(time.Second)}fmt.Println("釋放第", id, "個讀鎖")rwMutex.RUnlock() //釋放 讀鎖wg.Done()}func main() {var wg sync.WaitGroupfor i := 1; i < 3; i++ {wg.Add(1)go WriteData(&wg, i)}for i := 1; i < 4; i++ {wg.Add(1)go ReadData(&wg, i)}wg.Wait()fmt.Println("主程式執行完畢")}

  運行之後,就會發現,只有一個寫加鎖,只有寫解鎖之後,才允許加其他鎖;如果是加讀鎖之後,可以再加讀鎖。

 

Q-3

package mainimport ("fmt""sync")func demo() {fmt.Println("運行demo函數")}func main() {var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func() {demo()wg.Done()}()}wg.Wait()fmt.Println("主程式結束")}

  這個範例程式碼運行之後,會輸出10次“運行demo函數”,因為有10個goroutine,每個goroutine都運行了1次。

  現在的需求是:雖然有10個goroutine,但是希望只有一個goroutine中執行demo函數,如果一個goroutine執行過了demo函數,其他的goroutine就會忽略demo函數,不去執行demo,保證demo函數只被執行一次。

 

sync.once初始化

  sync.Once就是用來解決上面這個問題的:Once的作用就是多次調用,但只執行一次,Once只有一個方法->Once.Do(func),向Do中傳入一個函數,在第一次執行Once.Do()的時候,才執行傳入的func,以後在執行Once.Do(),就不會再執行傳入的func。

  樣本如下:

package mainimport ("fmt""sync")func demo() {fmt.Println("運行demo函數")}func main() {var wg sync.WaitGroupvar once sync.Oncefor i := 0; i < 10; i++ {wg.Add(1)go func() {once.Do(demo)//注意不要寫成once.Do(demo()),這樣寫是把demo()的運行結果傳入Dowg.Done()}()}wg.Wait()fmt.Println("主程式結束")}

  這樣就不會執行多次demo(),而只輸出一次“運行demo函數”

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.