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,跟预想的一致。

  • 相关阅读:
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
    自考感悟,话谈备忘录模式
    [每日一题] OCP1z0-047 :2013-07-26 alter table set unused之后各种情况处理
    Java实现 蓝桥杯 算法提高 p1001
    Java实现 蓝桥杯 算法提高 拿糖果
    Java实现 蓝桥杯 算法提高 拿糖果
    Java实现 蓝桥杯 算法提高 求arccos值
    Java实现 蓝桥杯 算法提高 求arccos值
    Java实现 蓝桥杯 算法提高 因式分解
    Java实现 蓝桥杯 算法提高 因式分解
  • 原文地址:https://www.cnblogs.com/feixiangmanon/p/13670927.html
Copyright © 2011-2022 走看看