为什么互斥锁比 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)
使用互斥体性能更好。
Atas ialah kandungan terperinci Mengapakah mutex lebih perlahan daripada saluran dalam golang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!