用于同步时通道和mutex的区别

用于同步时通道和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

简单解释一下,在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无法实现

你可能感兴趣的:(golang)