Go併發模式之 防止goroutine洩漏

2021-09-12 19:21:28 字數 3613 閱讀 7251

goroutine 有以下幾種方式被終止:

1。 當他完成了它的工作。

2。 因為不可恢復的錯誤, 它不能繼續工作

3。 當他被告知 需要終止工作。

我們可以簡單的使用前兩種方法, 因為這兩種方法隱含在你的演算法中, 但"取消工作" 又是怎樣工作的呢?

例如:這樣情況: 子goroutine 是否該繼續執行可能是以許多其他goroutine 狀態的認知為基礎的。

通常是 main goroutine 具有這種語境知識能夠告訴其子goroutine 終止。

下面看乙個 洩漏的例子/ (goroutine 沒有進行死亡處理的例子)

func main()  )

go func()

}()return completed

} dowork(nil)

//也許這裡有其他操作需要執行

fmt.println("done.")}*/

/**分析: dowork 的goroutine 在整個生命週期中都保留在記憶體中;顯然不合理,傳入的是nil 應該是更早的結束這個goroutine 才對。

怎麼解決呢,使用 done channel

分析: dowork 的goroutine 在整個生命週期中都保留在記憶體中;顯然不合理,傳入的是nil 應該是更早的結束這個goroutine 才對。

怎麼解決呢,使用 done channel

func main(), strings 

go func()

}}()

return terminated

} done := make(chan inte***ce{})

terminated := dowork(done, nil)

go func() ()

fmt.println("done.")

}//cancelling dowork goroutine...

//dowork exited.

//done.

*//**

分析: 儘管我們給我們的字串 channel 中傳遞了nil, 我們的goroutine仍然成功退出。 通過 1s 後 關閉dowork 中 goroutine 成功消除了我們的

goroutine 洩漏

分析: 儘管我們給我們的字串 channel 中傳遞了nil, 我們的goroutine仍然成功退出。 通過 1s 後 關閉dowork 中 goroutine 成功消除了我們的

goroutine 洩漏

這個例子 是: dowork 的 goroutine 從某個channel(作為引數傳進來) 中 for 讀取

下面這個例子: dowork 中的goroutine 向某個channel() 中寫入(for方式)資料

func main()

}()return randstream

} randstream := newrandstream()

fmt.println("3 random ints:")

for i:=1; i<=3; i++}//

//3 random ints:

//1: 5577006791947779410

//2: 8674665223082153551

//3: 6129484611666145821

*//**

解決方案: 像接收案例一樣,為生產者提供乙個通知他 退出 的 done channel:

問題: 在三次迭代後,我們的goroutine試圖將下乙個隨機數傳送到不需要的被讀取的 channel. 我們沒有告訴生產者它可以停止了。

解決方案: 像接收案例一樣,為生產者提供乙個通知他 退出 的 done channel:

func main()) 

}}()

return randstream

} done := make(chan inte***ce{})

randstream := newrandstream(done)

fmt.println(" 3 random ints:")

for i:=1; i<=3; i++

close(done)

//正在模擬進行的工作

time.sleep(1 * time.second)}*/

/**為了goroutine 不洩漏, 約定: 如果goroutine 負責建立 goroutine,他也負責 確保可以停止 goroutine

*/

為了goroutine 不洩漏, 約定: 如果goroutine 負責建立 goroutine,他也負責 確保可以停止 goroutine
or-channel   /  復合 done channel

希望將 多個 channel 合併為 乙個 done channel ;該channel 在 任何乙個元件channel 關閉時 ,都將關閉, 注意:元件中其他channel 可沒有關閉!!!

這種模式通過遞迴 和 goroutine 建立乙個復合 done chanenl .

func main()) 

or = func(channels ...

ordone := make(chan inte***ce{})

//建立goroutine 以便可以不受阻塞地等待我們 channel上的訊息

go func()

default :

select

}}()

return ordone

} //下面是使用or channel乙個例子

sig := func(after time.duration)

go func()()

return c

} start := time.now()

sig(2*time.hour),

sig(2*time.minute),

sig(1*time.second),

sig(5*time.second),

sig(10*time.second),

sig(1*time.hour),

sig(1*time.minute),

) fmt.printf("done after %v", time.since(start))

time.sleep(5*time.minute);

}

or 函式呼叫圖形分析:

分析: 在組成or channel 的 元件中有多個channel; 這些channel 需要不同時間才能關閉(1s 10s 1m 等等);但是現象是 1s後關閉的這個channel

(sig(1*time.second)) 導致 or channel 關閉。

這種模式:在系統中的模組交匯處非常有用。

Go之簡單併發

func calculate id int 使用go來實現併發 func main time.sleep 1e9 2 等待程式執行結束,避免無輸出 上面 是最基礎的併發,使用time.sleep做超時等待,將上面的超時等待換成sync.waitgroup func main i wg.wait wa...

Go併發模式之 約束

約束 在編寫併發 的時候,有以下幾種不同的保證操作安全的方法。1。用於共享記憶體的同步原語 如sync.mutex 2.通過通訊來 共享記憶體來進行同步 如 channel 在併發處理中還有其他幾種情況也是隱式併發安全的 3。不會發生改變的資料 4。受到保護的資料 約束 特定約束,和 詞法約束 特定...

Go併發模式 設計模式之複製請求

複製請求 程式正在處理 使用者的http請求,或者檢索乙個資料塊。你可以將請求分發到多個處理程式 無論是 goroutine 程序,還是伺服器 其中乙個將比其他 處理程式返回更快,可以 立即返回結果。下面例子 在 單個程序中,使用多個goroutine 作為處理程式。goroutine 將隨機休眠一...