最近发现同事在一个需要多并发的场景下, 使用channel来保证并发安全, 大概问了下原因, 他说感觉channel应该要比加锁的方式性能要好. 然后网上搜了下居然有 “Channel 优于锁机制” 这种言论, 不明确具体的使用场景就说出这种言论的人太不负责了, 在有些场景下比如不同的goroutinue之间进行通信, 那么使用channel是最好不过了, 但是在一些多并发场景下使用channel来保证并发安全, 那么性能表现肯定比不上直接加锁, 代码的复杂度也相差无几.
下面来简单的做一个 benchmark, 来看一看 Mutex 和 channel 的性能差别.
首先在一个目录下新建两个文件:
- main.go
- main_test.go
main.go 文件内容如下:
// main.go package main import "sync" var mutex = sync.Mutex{} var ch = make(chan bool, 1) func UseMutex() { mutex.Lock() mutex.Unlock() } func UseChan() { ch <- true <-ch }
main_test.go 文件内容如下:
// main_test.go package main import "testing" func BenchmarkUseMutex(b *testing.B) { for n := 0; n < b.N; n++ { UseMutex() } } func BenchmarkUseChan(b *testing.B) { for n := 0; n < b.N; n++ { UseChan() } }
然后在该文件夹下面执行如下命令进行 benchmark:
$ go test -bench=.
压测结果如下:
BenchmarkUseMutex-4 100000000 17.9 ns/op BenchmarkUseChan-4 20000000 66.2 ns/op PASS ok _/golang/bench/mutex_chan 3.239s
根据上面的压测结果来看, 使用加锁的方式性能是使用channel的方式性能的 3.6倍 左右, 这个数值可不低啊. 所以在做服务端开发的时候, 对性能有所疑惑的时候一定要自己做一下benchmark, 不能人云亦云.