协程锁

作者: 酷走天涯 | 来源:发表于2018-12-24 09:24 被阅读11次
  • 什么是竞争
  • Mutex 的使用

什么是竞争

看下面的代码

package main

import (
    "sync"
    "fmt"
)

var total = 0

func add(num int,ws * sync.WaitGroup){
   total += 1
   ws.Done()
}

func main() {
  var ws sync.WaitGroup
  ws.Add(1000)
  for i:=0;i<1000;i++{
      go add(1,&ws)
  }
  ws.Wait()
  fmt.Println(total)
}

我们对一个变量total 进行1000次 +1 操作,不过我们是在多个协程中进行的,猜猜结果如何,我们运行五次看结果

image.png image.png image.png image.png image.png

竞争发生的概率,和你的协程数量成正比,如果你的协程数很少的话,可能运行几百次发现不了这个现象

那如何避免这个问题呢?


Mutex

Mutex 用于提供一种加锁机制(Locking Mechanism),可确保在某时刻只有一个协程在临界区运行,以防止出现竞态条件。

直接看代码

package main

import (
    "sync"
    "fmt"
)

var total = 0

func add(num int,ws * sync.WaitGroup,mutex *sync.Mutex){
    mutex.Lock()
   total += 1
   mutex.Unlock()
   ws.Done()
}

func main() {
  var ws sync.WaitGroup
    mutex := sync.Mutex{}
    ws.Add(1000)
  for i:=0;i<1000;i++{
      go add(1,&ws,&mutex)
  }
  ws.Wait()
  fmt.Println(total)
}

运行结果如下

image.png

sync.Mutex 是一个结构体 在操作元素的时候 mutex.Lock() 加锁 执行完毕后 mutex.Unlock()解锁


使用信道处理竞争

package main  
import (  
    "fmt"
    "sync"
    )
var x  = 0  
func increment(wg *sync.WaitGroup, ch chan bool) {  
    ch <- true
    x = x + 1
    <- ch
    wg.Done()   
}
func main() {  
    var w sync.WaitGroup
    ch := make(chan bool, 1)
    for i := 0; i < 1000; i++ {
        w.Add(1)        
        go increment(&w, ch)
    }
    w.Wait()
    fmt.Println("final value of x", x)
}

通过使用 Mutex 和信道,我们已经解决了竞态条件的问题。那么我们该选择使用哪一个?答案取决于你想要解决的问题。如果你想要解决的问题更适用于 Mutex,那么就用 Mutex。如果需要使用 Mutex,无须犹豫。而如果该问题更适用于信道,那就使用信道。:)

由于信道是 Go 语言很酷的特性,大多数 Go 新手处理每个并发问题时,使用的都是信道。这是不对的。Go 给了你选择 Mutex 和信道的余地,选择其中之一都可以是正确的。

总体说来,当 Go 协程需要与其他协程通信时,可以使用信道。而当只允许一个协程访问临界区时,可以使用 Mutex。

就我们上面解决的问题而言,我更倾向于使用 Mutex,因为该问题并不需要协程间的通信。所以 Mutex 是很自然的选择。

我的建议是去选择针对问题的工具,而别让问题去将就工具。:)

相关文章

  • 协程锁

    什么是竞争 Mutex 的使用 什么是竞争 看下面的代码 我们对一个变量total 进行1000次 +1 操作,不...

  • GO的锁和原子操作分享

    [TOC] GO的锁和原子操作分享 上次我们说到协程,我们再来回顾一下: 协程类似线程,是一种更为轻量级的调度单位...

  • python异步协程(aiohttp,asyncio)

    python异步协程 环境:python3.7.0 协程 协程,英文叫做 Coroutine,又称微线程,纤程,协...

  • 协程(三)IEnumerable、IEnumerator、for

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(五)简单模拟协程

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(一)基本使用

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(六)有关优化

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(二)协程什么时候调用

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(四)yield与迭代器

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • Coroutine协程

    与基于锁的并发相对; 1.不使用锁,没有线程上下文切换开销; 2.多进程+协程,充分利用多CPU Python对协...

网友评论

      本文标题:协程锁

      本文链接:https://www.haomeiwen.com/subject/escyzftx.html