为什么互斥锁比 golang 中的通道慢?
为什么互斥锁比 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 中的通道慢?的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341