為什麼互斥鎖定比 golang 中的頻道慢?這是一個常見的問題,許多開發者都在探索這個問題的原因。互斥鎖和通道是 golang 中常用的同步機制,它們在同時編程中扮演著重要的角色。然而,有時我們會發現互斥鎖的效能比通道差,這是為什麼呢? php小編柚子將在本文中為大家解答這個問題,幫助讀者更能理解並發程式設計的效能差異。
我正在製作一個程式來抓取網站並返回它們的狀態。
我用不同的方法寫了這個程式。第一個使用互斥體來防止並發寫入映射,以便我可以擺脫資料競爭。然後出於同樣的目的,我用管道來實現它。但是當我進行基準測試時,我意識到使用通道實現它比實現互斥體要快得多。我想知道為什麼會發生這種情況?為什麼互斥體缺乏性能?我對互斥體做錯了什麼嗎?
基準結果:
程式碼
package concurrency import "sync" type websitechecker func(string) bool type result struct { string bool } func checkwebsites(wc websitechecker, urls []string) map[string]bool { results := make(map[string]bool) var wg sync.waitgroup var mu sync.mutex for _, url := range urls { wg.add(1) go func(u string) { defer wg.done() mu.lock() results[u] = wc(u) mu.unlock() }(url) } wg.wait() return results } func checkwebsiteschannel(wc websitechecker, urls []string) map[string]bool { results := make(map[string]bool) resultchannel := make(chan result) for _, url := range urls { go func(u string) { resultchannel <- result{u, wc(u)} }(url) } for i := 0; i < len(urls); i++ { r := <-resultchannel results[r.string] = r.bool } return results }
測試程式碼
package concurrency import ( "reflect" "testing" "time" ) func mockWebsiteChecker(url string) bool { time.Sleep(20 * time.Millisecond) if url == "https://localhost:3000" { return false } return true } func TestCheckWebsites(t *testing.T) { websites := []string{ "https://google.com", "https://localhost:3000", "https://blog.gypsydave5.com", } want := map[string]bool{ "https://google.com": true, "https://blog.gypsydave5.com": true, "https://localhost:3000": false, } got := CheckWebsites(mockWebsiteChecker, websites) if !reflect.DeepEqual(got, want) { t.Errorf("got %v, want %v", got, want) } } func BenchmarkCheckWebsites(b *testing.B) { urls := make([]string, 1000) for i := 0; i < len(urls); i++ { urls[i] = "a url" } b.ResetTimer() for i := 0; i < b.N; i++ { CheckWebsites(mockWebsiteChecker, urls) } } func BenchmarkCheckWebsitesChannel(b *testing.B) { urls := make([]string, 1000) for i := 0; i < len(urls); i++ { urls[i] = "a url" } b.ResetTimer() for i := 0; i < b.N; i++ { CheckWebsitesChannel(mockWebsiteChecker, urls) } }
在我看來,使用互斥版本的程式碼,您不僅可以保護results
映射,還可以保護wc
(只有在獲得鎖後才能進行調用,因此您可以有效地序列化調用)。只有在右側準備好後,發送到 chan 才會鎖定通道,因此對 wc
的呼叫可以同時發生。看看程式碼是否像
go func(u string) { defer wg.Done() r := wc(u) mu.Lock() results[u] = r mu.Unlock() }(url)
使用互斥體表現較好。
以上是為什麼互斥鎖比 golang 中的頻道慢?的詳細內容。更多資訊請關注PHP中文網其他相關文章!