zoukankan      html  css  js  c++  java
  • golang开发:WaitGroup Mutex

    CSP 是 Communicating Sequential Process 的简称,中文可以叫做通信顺序进程,是一种并发编程模型,最初于Tony Hoare的1977年的论文中被描述,影响了许多编程语言的设计。

    golang CSP模型

    golang语言并没有完全实现了CSP模型的所有理论,仅仅是借用了 process和channel这两个概念。process是在golang语言上的表现就是 goroutine, 是实际并发执行的实体,每个实体之间是通过channel通讯来实现数据共享。
    最经典的数据通信共享理论

    以通信的方式来共享内存

    Do not communicate by sharing memory; instead, share memory by communicating
    

    不要以共享内存的方式来通信,相反,要通过通信来共享内存。
    这是golang实现高并发的基础通信理论。
    在golang语言上面,就是通过channel实现多个goroutine的数据通信。

    sync.WaitGroup使用

    如果需要让多个goroutine都执行完成,就是用使用time.sleep,延迟几秒保证每个goroutine都能执行到。

    func testPrint(i int) {
    	fmt.Println(i)
    }
    func main() {
    	for i:=0;i<5;i++ {
    		go testPrint(i)
    	}
    	time.Sleep(time.Second)
    }
    

    但是在生产项目里面就没法这么写了,延迟1S有可能所有goroutine没执行完成,延迟1000S可能1毫秒就执行完了,其他999S都是等待,延长了程序执行时间。
    所以就有sync.WaitGroup

    func testPrint(wg *sync.WaitGroup, i int) {
    	fmt.Println(i)
    	wg.Done()
    }
    func main() {
    	var wg = new(sync.WaitGroup)
    	for i:=0;i<5;i++ {
    		wg.Add(1)
    		go testPrint(wg,i)
    	}
    	wg.Wait()
    }
    

    WaitGroup比较容易理解,其实就是一个内部计数器,在执行goroutine行为之前执行 wg.Add(1),给计数器+1,执行完之后,执行wg.Done(),表示这个goroutine执行完成,计数器内部-1,wg.Wait()会阻塞代码的运行,等待所有的添加进WaitGroup的goroutine全部执行完毕(计数器减为0),再退出程序。
    非常完美的解决了等待所有goroutine执行完毕的需要。

    sync.Mutex

    sync.Mutex,互斥锁排它锁。
    我们需要维护一个变量,保证每个goroutine都能成功的修改它,如果没有互斥锁可能就是下面的代码

    func testPrint(wg *sync.WaitGroup, i int) {
    	count++
    	fmt.Println(i)
    	wg.Done()
    }
    var count int
    func main() {
    	count = 0
    	var wg = new(sync.WaitGroup)
    	for i:=0;i<500;i++ {
    		wg.Add(1)
    		go testPrint(wg,i)
    	}
    	wg.Wait()
    	fmt.Printf("count:%d",count)
    }
    

    预期应该是特定的值,500,其实经常性的不是500.就是因为多个goroutine同时去修改count值了,加上互斥锁试一下。

    func testPrint(wg *sync.WaitGroup, i int) {
    	defer func() {
    		mu.Unlock()
    	}()
    	mu.Lock()
    	count++
    	fmt.Println(i)
    	wg.Done()
    }
    var count int
    var mu *sync.Mutex
    func main() {
    	count = 0
    	mu = new(sync.Mutex)
    	var wg = new(sync.WaitGroup)
    	for i:=0;i<500;i++ {
    		wg.Add(1)
    		go testPrint(wg,i)
    	}
    	wg.Wait()
    	fmt.Printf("count:%d",count)
    }
    

    结果是定值500,跟预想的一致。

  • 相关阅读:
    02-04UML类图之--关联关系(Association)
    02-03UML类图之--实现关系(Implementation)
    02-02UML类图之--泛化关系(generalization)
    02-01UML类图之--依赖关系(Dependence)
    01-07.合成复用原则(Composite Reuse Principle)
    01-06.迪米特法则(Demeter Principle)
    算法 - 二叉搜索树的第k个结点
    算法
    InteliJ IDEA社区版 两款插件变身旗舰版
    intelliJ idea自定义代码折叠
  • 原文地址:https://www.cnblogs.com/feixiangmanon/p/13670927.html
Copyright © 2011-2022 走看看