Golang的併發安全

2021-10-07 16:36:27 字數 2592 閱讀 9496

channel是go中代替共享記憶體的通訊方式,

channel從底層實現上是一種佇列,

在使用的時候需要通道的傳送方和接收方需要知道資料型別和具體通道。

如果有一端沒有準備好或訊息沒有被處理會阻塞當前端。

actor模型:在actor模型中,主角是actor,

類似一種worker,actor彼此之間直接傳送訊息,

不需要經過什麼中介,訊息是非同步傳送和處理的

actor模型描述了一組為了避免併發程式設計的常見問題的公理:

1.所有actor狀態是actor本地的,外部無法訪問。

2.actor必須只有通過訊息傳遞進行通訊。 

3.乙個actor可以響應訊息:推出新actor,改變其內部狀態,或將訊息傳送到乙個或多個其他參與者。

4.actor可能會堵塞自己,但actor不應該堵塞它執行的執行緒。

cap模型中,worker之間不直接彼此聯絡,

而是通過不同channel進行訊息發布和偵聽。

訊息的傳送者和接收者之間通過channel松耦合,

傳送者不知道自己訊息被哪個接收者消費了,

接收者也不知道是哪個傳送者傳送的訊息。

go語言的csp模型是由協程goroutine與通道channel實現:

go協程goroutine: 是一種輕量執行緒,它不是作業系統的執行緒,

而是將乙個作業系統執行緒分段使用,通過排程器實現協作式排程。

是一種綠色執行緒,微執行緒,它與coroutine協程也有區別,

能夠在發現堵塞後啟動新的微執行緒。

通道channel: 類似unix的pipe,用於協程之間通訊和同步。

協程之間雖然解耦,但是它們和channel有著耦合。

cap的worker彼此之間不直接連線,通訊是通過channel實現的

actor之間是直接通訊

channel不但可以傳遞訊息(資料),也可以用作事件通知。

package main

func main()) //傳送空結構體(通知)

c := make(chan string) //資料傳輸通道

go func() ()

c <- "hi!" //傳送訊息

<-done //阻塞

}

同步模式下需要有goroutine配合,否則會一直阻塞。

非同步模式時當緩衝區沒有滿或者資料未讀完的時候,不會出現阻塞:

package main

func main()

//在程式中非同步通道可以提高程式的效能減少排隊阻塞

//channel變數本身為指標

channel的收發,channel中還可以使用ok-idom和range模式處理資料

package main

func main() )

c := make(chan int)

go func()

println(x)

} }()

c <- 1

c <- 2

c <- 3

close(c)

<-done

donr := make(chan struct{})

cr := make(chan int)

go func()

}()cr <- 1

cr <- 2

cr <- 3

close(cr)

<-donr

}//及時使用close函式關閉通道引發結束通知,避免出現可能的死鎖

一次性事件使用close效率更高,沒有多餘的開銷。

使用sync.cond實現單播或廣播事件

使用close或nil通道時的原則

向已關閉通道傳送資料,引發panic

從已關閉接收資料,返回以緩衝資料或零值(在使用channel傳送結束時最好使用空struct)

無論收發,nil通道都會阻塞

在使用goroutine和channel時一般使用工廠方法繫結

package main

import "sync"

type receive struct

func newr() *receive

r.add(1)

go func()

}()return r

}func main()

//recv : 1

//recv : 2

通道可能會引發goroutine leak,指goroutine處於傳送或接收阻塞狀態,但沒有未被喚醒。gc並不收集此類資源,導致他們在佇列裡長久休眠,形成資源洩露

package main

import (

"runtime"

"time"

)func testv()()}}

func main()

}//godebug="gctrace=1,schedtrace=1000,scheddetail=1" ./channel5

監控程式goroutine狀態,檢視監控結果可以看出有大量的goroutine處於chan receive狀態,不能結束

golang 之sync 併發安全鎖

讓乙個程式併發安全並不需要其中的每乙個具體型別都是併發安全的。實際上併發安全的型別其實是特例而不是普遍存在的,所以僅在文件指出型別是安全的情況下,才可以併發的訪問乙個變數。與之對應的是,匯出的包級別函式通常可以認為是併發安全的。因為包級別的變數無法限制在乙個goroutine內。所以那些修改這些變數...

golang 併發 共享資源安全

首先,我們需要知道 在golang中,多 goroutine 同時操作乙個共享資源時 我們需要保障資源的安全 我們對資源的操作結果要符合我們的預期 當我們未對資源做保護操作時,多個goroutine同時操作同一資源時,就可能會出現問題 例如 count 1 有a b兩個 goroutine 同時拿到...

golang 閒談併發

對於併發這個概念,我想大家都對它不會陌生,今天就從簡單的火車站賣票問題出發,來談談併發。首先宣告本文的 是golang 因為最近開始用的就是golang 對於其他的語言其實也是相通的,那麼正式開始正題吧,首先我們來看看,賣一張票,總票數就減一,一般來說我們會這麼寫 package main impo...