用于同步时通道和mutex的区别
通道是Go语言内建的特性之一,用来在程序内部传输数据,很容易用于同步目的。比如构建一个缓存为1的channel
c:=make(chan bool,1)`,当需要独占的获得时,就可以<-c,而要释放时,执行c<-true。
Mutex是sync包定义的一个类型,实现了互斥锁,定义了Lock()/Unlock()方法来获得/释放锁.
从功能角度看,使用通道同步和使用Mutex同步完全等价,但是从性能的角度看,差别很大,下面用一个例子来说明:
package main
import (
"sync"
"fmt"
"time"
)
func f(){
for{
<-c
if i==Max {
wg.Done()
c<-true
return
}else{
i++
c<-true
}
}
}
func g(){
for{
l.Lock()
if i==Max{
wg.Done()
l.Unlock()
return
}else{
i++
l.Unlock()
}
}
}
var i int
var l sync.Mutex
var wg sync.WaitGroup
var c chan bool
var Max=500000
var Num=100
func init(){
c=make(chan bool,1)
c<-true
}
func main(){
start:=time.Now()
wg.Add(Num)
for j:=0;j<Num;j++{
go f()
}
wg.Wait()
fmt.Println(time.Now().Sub(start),i,"channel")
i=0
start=time.Now()
wg.Add(Num)
for j:=0;j<Num;j++{
go g()
}
wg.Wait()
fmt.Println(time.Now().Sub(start),i,"sync.Mutex")
}
简单解释一下,在main()中,生成Num个goroutine,都是执行某个函数,然后等待这些goroutine返回,计时。f()和g()差不多,检测i是否等于Max,如果相等,那么返回;如果不等,那么增加i的值。不同的是f()使用通道作为同步,而g()使用Mutex作为同步。输出结果是:
62.648078ms 500000 channel
13.682324ms 500000 sync.Mutex
由此可以看出,作为同步原语使用时,Mutex性能要好于通道,同时也比通道使用简单,不需要如下面那样构建和初始化
c=make(chan bool,1)
c<-true
然而,通道作为语言的内建特性,即使仅仅用于同步,也有其读到之处。**select**语句允许在多个通道上等待,如:
data:=make([]string,5)
c:=make([]chan bool,5)
for i:=0;i<5;i++{
c[i]=make(chan bool,1)
c[i]<-true
}在进过初始化后,我们就可以使用select语句来选择一个通道元素来读取
select {
id:=0
case <-c[0]:
case <-c[1]:
id=1
case <-c[2]:
id=2
case <-c[3]:
id=3
case <-c[4]:
id=4
...
//访问data[id]
c.[id]<-true
}
只要有一个元素可用,我们就不会在这里阻塞。这一点,Mutex无法实现
本文对比了Go语言中通道和Mutex同步机制的性能差异,通过实例展示了在高并发场景下,Mutex相较于通道能提供更好的性能表现。同时,介绍了通道的多重使用特性以及select语句在并发控制上的灵活性。
2310

被折叠的 条评论
为什么被折叠?



