go并发编程之五(sync之互斥锁Mutex)

Mutex互斥锁相关的介绍使用

1. 互斥锁的定义

互斥锁:是一种同步机制,用于在存在许多执行线程的环境中强制限制对资源的访问。锁旨在实施互斥 并发控制策略。

我们来看一个示意图:

在这里插入图片描述

没有锁的时候,A、B、C同时争抢资源E,像打架似的谁也不让谁,有锁了以后,只有A拥有该资源,B/C只能在外面等待
索被释放

2. 互斥锁的使用

想象我们有1w个商品券发给同时发给1w个人,每个人都会得到一张商品券,每张商品券核销码都不一样,且只能核销一次
看如下简化代码:

package main

import (
	"fmt"
	"sync"
)

type GoodsNum struct {
	value int
	lock sync.Mutex // 0
}

func decrGoodNum(clientId int , good *GoodsNum,group *sync.WaitGroup) {
	good.lock.Lock() // 1
	defer func() {
		good.lock.Unlock() //2
		group.Done()
	}()
	good.value--
	fmt.Println("client ",clientId," get the good and good num left ",good.value)
}

func main() {

	var waitGroup sync.WaitGroup
	l := sync.Mutex{} //3
	good := GoodsNum{
		value:10000,
		lock:l, //4
	}
	start := time.Now().UnixNano()
	waitGroup.Add(10000)
	for i := 1 ; i<= 10000 ; i++ {
		go decrGoodNum(i,&good,&waitGroup)
	}
	waitGroup.Wait()
    end := time.Now().UnixNano()
	fmt.Println("exec complete good num left ",good.value)
	fmt.Println("cast time ",end - start,"ns")
}

不加锁的情况下,我们注释掉 0/1/2/3/4 这五处代码,然后执行,结果截图如下:

在这里插入图片描述

然后我们打开这五处注释,执行,结果截图如下

扫描二维码关注公众号,回复: 5282451 查看本文章

在这里插入图片描述

然后我们发现,我们没有加锁时,居然多出来 12 张没有发完,这就是之前提到的原子性操作,多个线程同时拿到同一个资源时,同时操作会导致结果的不确定性,然后我们加了互斥锁以后,结果始终是0。
互斥锁对性能稍微有点开销,所以我们尽可能的将需要加锁的代码减少到最少。

最佳实践:将要锁住的代码片段放入匿名函数

go func(){
	lock.lock()
	defer lock.unlock()
	//your code here 
}()

有一篇讲解go使用锁的例子,非常好,如果你想深入,请阅读他:https://hackernoon.com/dancing-with-go-s-mutexes-92407ae927bf

猜你喜欢

转载自blog.csdn.net/wujiangwei567/article/details/86688218