日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go中如何使用easyjson_如何在 Go 中编写无 Bug 的 Goroutines?

發布時間:2024/10/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go中如何使用easyjson_如何在 Go 中编写无 Bug 的 Goroutines? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點上方藍色“云原生領域”關注我,設個星標,不會讓你失望

GO 并發

Go 以其并發性著稱,深受人們喜愛。go 運行時管理輕量級線程,稱為 goroutines。goroutine 的編寫非??焖俸唵?。

你只需在你想異步執行的函數前輸入 go,程序就會在另一個線程中執行。

聽起來很簡單?

goroutines 是 Go 編寫異步代碼的方式。

重要的是要了解 goroutine 和并發的工作原理。Go 提供了管理 goroutine 的方法,使它們在復雜的程序中更容易管理和預測。

因為 goroutine 非常容易使用,所以它們很容易被濫用。

1 在異步例程中不要對執行順序進行假設。

在 Go 中調度并發任務時,要記住異步任務的不可預知性。

可以將異步與同步計算融合在一起,但只要同步任務不對異步任務做任何假設即可。

對于初學者來說,一個常見的錯誤是創建一個 goroutine,然后根據該 goroutine 的結果繼續執行同步任務。例如,如果該 goroutine 要向其作用域外的變量寫入,然后在同步任務中使用該變量。

假設執行順序

package?main

import?(
?"time"
?"fmt"
)

func?main()?{
?var?numbers?[]int?//?nil

?//?start?a?goroutine?to?initialise?array
?go?func?()?{
??numbers?=?make([]int,?2)
?}()
??
??//?do?something?synchronous
??if?numbers?==?nil?{
????time.Sleep(time.Second)
??}
??numbers[0]?=?1?//?will?sometimes?panic?here
?fmt.Println(numbers[0])
}

這種模式會導致不可預知的行為。它引入的代碼導致了我們無法控制的因素;這些因素與 go 運行時有關,更具體地說,就是它如何管理 goroutines。

編寫這樣的代碼意味著假定 goroutine 將在需要結果之前完成它的任務。

首先,在沒有某種管理技術(我們將討論)的情況下,交叉異步和同步代碼的成功將取決于 CPU 的可用性。

這意味著如果有 CPU 密集型的進程與 goroutines 同時運行,那么執行的時間將會有所不同。

其次,不同的編譯器將以不同的方式調度 goroutines。因此,安全的做法是不要認為 goroutine 會在同步任務期間完成。

如何確保 goroutine 已經完成?

使用 channel

在異步任務完成時使用 channel 來通知

channel 應該用于接收來自異步任務(如 goroutines)的值。

如果你想阻止進一步的執行,直到最終從 channel 讀取一個值來釋放它,可以使用緩沖通道。

如果你想要 1 進 1 出的行為,那么使用非緩沖通道。

在本例中,使用 channel,我們可以確保主任務等待直到異步任務完成。當 goroutine 完成它的工作時,它將通過 done channel 發送一個值,該值將在對 numbers 數組進行操作之前被讀取。

package?main

import?(
?"time"
?"fmt"
)

func?main()?{
?var?numbers?[]int?//?nil
?done?:=?make(chan?struct{})
?//?start?a?goroutine?to?initialise?array
?go?func?()?{
??numbers?=?make([]int,?2)
??done?struct{}{}
?}()
??
??//?do?something?synchronous
??//?read?done?from?channel
??numbers[0]?=?1?//?will?not?panic?anymore
?fmt.Println(numbers[0])?//?1
}

盡管這是一個人為的示例,但你可以看到它在什么地方會很有用:當主線程與 goroutine 并行處理復雜工作時。這兩個任務可以同時完成,而不可能出現 panic。

2 避免跨并發線程訪問可變數據

跨多個 goroutine 訪問可變數據是將數據競爭引入程序的“好方法”。

數據競爭是指兩個或多個線程(或這里的goroutine)并發訪問同一內存位置。

這意味著跨線程訪問相同的變量可能會產生不可預測的值。如果兩個進程同時訪問同一個變量,有兩種可能性:

  • 兩個線程的值是相同的(不正確)。
  • 對于較慢/較晚的線程,該值是不同的。(正確)

如果較慢/較晚的線程讀取了一個已被較快/較早的線程修改過的更新值,那么它將對更新后的值進行操作。這是預期的行為。

否則,就像在數據競爭中看到的那樣,兩個線程將產生相同的值,因為它們都將對未更改的值進行操作。

1000 種可能的數據競爭

在這個例子中,我們使用 sync.WaitGroup 來保持程序運行,直到所有的 goroutine 完成,但我們并沒有控制對每個 goroutine 內變量的訪問。

package?main

import?(
?"fmt"
?"sync"
)

func?main()?{
?a?:=?0?//?data?race
?var?wg?sync.WaitGroup
?wg.Add(1000)
?for?i?:=?0;?i?1000;?i++?{
??go?func()?{
???defer?wg.Done()
???a?+=?1
??}()
?}
?wg.Wait()
???fmt.Println(a)?//?could?theoretical?be?any?number?0-1000?(most?likely?above?900)
}

這段代碼可以打印 0-1000 之間的任何數字,具體取決于發生的數據競爭數量。

這段代碼的工作原理是,兩個線程將對同一個變量各執行 2 次操作,總共有 2 次讀 + 2 次寫。

在兩個線程都會產生相同的值的情況下,在對變量進行任何寫入之前,兩個(2)讀都必須發生。

使用互斥鎖在 goroutines 之間共享內存

為了防止 goroutines 中的數據競爭,我們需要同步對共享內存的訪問。我們可以使用互斥來實現這一點。互斥鎖將確保我們不會在同一時間讀取或寫入相同的值。

它本質上是暫時鎖定對一個變量的訪問。

package?main

import?(
?"fmt"
?"sync"
)

func?main()?{
?a?:=?0
?var?wg?sync.WaitGroup

?var?mu?sync.Mutex?//?guards?access

?wg.Add(1000)
?for?i?:=?0;?i?1000;?i++?{
??go?func()?{
???mu.Lock()
???defer?mu.Unlock()
???defer?wg.Done()
???a?+=?1
??}()
?}
?wg.Wait()
?fmt.Println(a)?//?will?always?be?1000
}

就這么簡單。

這段代碼總是打印 1000,因為對同一個變量的每個后續操作都會對更新后的值進行操作。

3 不要寫應該同步的異步任務

Goroutines 通常被認為是后臺任務。它們被視為可以與主程序同時運行的小任務,通過 goroutine 將其委托給另一個線程。

當學習 Go 時,你往往會想到使用 goroutine 來盡量減少阻塞操作,或者讓我們的程序性能更強。

但由于對 goroutine 的看法如此簡單,很容易養成 "以防萬一" 的習慣,把所有東西都做成 goroutine。

如果某些任務本質上是同步的,但你卻異步地使用了它們,這就會造成問題。

并非所有的任務都應該是一個 goroutine。

有些任務需要秩序。在許多進程中,下一個任務取決于前一個任務的結果。這些順序性的任務會讓你的程序出錯,勢必需要讓這些區域更加同步。

所以有些情況下,你還不如直接忘掉goroutine,一開始就保持同步。

用無限循環浪費 CPU

在這個精心設計的示例中,我們有一個程序,它將所有內容委托給 goroutines,并使用 for 循環來保持程序運行。

這是一個如何不控制 Go 程序流程的例子。

func?main()?{
??go?doSomething()
??go?doSomethingElse()
??
??//?execute?everything?as?a?goroutine
??
??for?{?//?this?keeps?the?program?running
??
??}
}

最好保持簡單。你可以通過把你的程序看作是主線程加上附加線程的方式來防止這種類型的不良做法。你可以讓主線程以同步的方式運行,但如果需要,可以通過 goroutines 將任務委托給另一個線程。

有更好的方法可以控制程序的流程,比如通過 WaitGroups 或 Channels。

使用 WaitGroup 的控制流程

與其浪費寶貴的 CPU 資源,不如使用 WaitGroup 向運行時表明,在程序退出之前,你正在等待 n 個任務的完成。這樣就不會讓 CPU 一直在無限循環中旋轉。

func?doSomething(wg?*sync.WaitGroup)?{
??//?do?something?here
??fmt.Println("Done")
??defer?wg.Done()
}

func?main()?{
??var?wg?sync.WaitGroup
??wg.Add(1)
??defer?wg.Wait()
??go?doSomething(&wg)
??go?doSomethingElseSync()
??
??//?program?will?wait?until?doSomething?&?doSomethingElseSync?is?complete

}

首先,您需要將等待完成的任務數量作為參數提供給 wg.Add() 函數。

放置 wg.Wait() 很重要。這是程序中執行將暫停的地方,等待所有任務完成。

一旦任務完成,您可以使用 wg.Done() 讓程序知道。

4 不要讓 goroutines 掛起

確保處理不再使用的 goroutines。持續運行的 Goroutines 將會阻塞并浪費寶貴的 CPU 資源。

如果 goroutine 試圖將值發送到沒有任何讀取并等待接收值的 channel,就會發生這種情況。這就意味著這條 channel 將永遠卡在那里。

9 個掛起的 goroutine

在這個例子中,channel 只被讀取一次。這意味著 9 個 goroutines 在等待通過 channel 發送一個值。

func?sendToChan()?int?{
?channel?:=?make(chan?int)
?for?i?:=?0;?i?10;?i++?{
??i?:=?i
??go?func()?{
???channel?//?9?hanging?goroutines
??}()
?}
?return?}

為了避免這種情況,請處理不再需要的 goroutines 來釋放 CPU。

使通道緩沖

使用緩沖通道意味著您正在為通道提供空間來存儲附加值。

對于當前的示例,這意味著所有的 goroutines 都將成功執行,不會阻塞。

func?sendToChan()?int?{
?channel?:=?make(chan?int,?9)
?for?i?:=?0;?i?10;?i++?{
??i?:=?i
??go?func()?{
???channel?//?all?goroutines?executed?successfully
??}()
?}
?return?}

不要在不知道什么時候停止的情況下開始一個 goroutine。

在不知道何時停止的情況下啟動一個 goroutine 會導致以下行為,即 goroutine 被阻塞或浪費 CPU 資源。

您應該總是知道什么時候 goroutine 將停止,什么時候不再需要它。

您可以通過 select 語句和 channel 來實現這一點

done?:=?make(chan?bool)
go?func()?{
??for?{
????select?{
??????case?????????return
???????default:
????}
??}
}()
done?true

這本質上是一個帶有退出條件的異步 for-loop。

重要的邏輯將在默認條件下編寫。

當值被發送到 done 通道時,循環將停止,正如 done 所示。這意味著 channel 讀取 成功并返回。

”“

譯自:https://itnext.io/how-to-write-bug-free-goroutines-in-go-golang-59042b1b63fb

來都來了,點個“再看”再走叭~~

總結

以上是生活随笔為你收集整理的go中如何使用easyjson_如何在 Go 中编写无 Bug 的 Goroutines?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久男人网 | 中文字幕不卡视频 | 午夜影院在线观看18 | 精品国产乱码久久久久夜深人妻 | av导航网站 | 粉嫩av一区二区三区天美传媒 | 国产日产欧美一区二区三区 | 色偷偷888欧美精品久久久 | 国产又粗又猛又爽又黄的视频在线观看动漫 | 天天干天天色天天射 | a天堂中文在线 | 成人毛片大全 | 麻豆网站在线 | 亚洲性夜| 国产青青视频 | 日日爱影视 | 高h调教冰块play男男双性文 | 日日色综合 | 国产在视频线精品视频 | 五月天婷婷激情网 | 欧美12--15处交性娇小 | 五月天综合在线 | 精品人妻伦一二三区免费 | 牛牛精品一区二区 | 黄色片网站免费在线观看 | 毛片看 | 欧美国产激情 | 国产剧情精品在线 | 我们好看的2018视频在线观看 | 日韩高清不卡一区 | 欧美一区二区三区爱爱 | 国产在线一级 | 男女黄床上色视频免费的软件 | 麻豆入口 | 免费成人深夜在线观看 | 亚洲综合日韩在线 | 91福利小视频 | 99精品欧美一区二区蜜桃免费 | 爆操巨乳美女 | 久草视频在线资源站 | 天天干夜夜看 | 伊人伊色 | 久久综合久色欧美综合狠狠 | 日批视频在线播放 | 少妇激情一区二区三区视频 | 欧美日韩女优 | 国产精品午夜一区二区 | 久久精品—区二区三区舞蹈 | 夜夜嗨一区二区三区 | 久久久久亚洲av无码网站 | 国产亚洲自拍一区 | 亚洲你懂的| 国产女人视频 | 国产一区二区三区电影在线观看 | 欧美又粗又深又猛又爽啪啪九色 | 日韩在线观看一区二区 | 婷婷一区二区三区 | 天天插天天狠天天透 | 亚洲在线影院 | 粉嫩av网| 中文在线日韩 | 夜噜噜 | 无码一区二区三区免费 | 91视频在线免费看 | 亚洲一区欧洲一区 | 日本一区二区高清视频 | 嫩草一二三 | 两根大肉大捧一进一出好爽视频 | 久久伊人国产 | 五月婷婷激情综合网 | 欧美极品jizzhd欧美爆 | 激情五月婷婷色 | 黄页av | 国产精品分类 | 麻豆精品在线 | 亚洲成av人片一区二区 | 欧美国产精品一区二区 | www.色网站| 91九色国产视频 | 九九久久国产精品 | 国产有码在线观看 | 亚洲国产精品成人久久蜜臀 | 艹久久 | 亚洲经典久久 | 日本在线中文 | 欧美日韩国产在线 | 色爽av| 亚洲av无码日韩精品影片 | 国产精品伦一区二区三级视频 | 亚洲精品影院在线 | 日本一区高清 | 让男按摩师摸好爽 | 亚洲精品麻豆 | 中文字幕在线观看视频一区二区 | 成年人福利 | 亚洲老老头同性老头交j | 最新色站| 最新中文字幕一区 | 免费看av毛片|