用Go语言怎么样实现互斥锁,代码是什么
导读:这篇文章主要给大家介绍“用Go语言怎么样实现互斥锁,代码是什么”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“用Go语言怎么样实现互斥锁,代码是什么”文章能对大家有所帮助。...
这篇文章主要给大家介绍“用Go语言怎么样实现互斥锁,代码是什么”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“用Go语言怎么样实现互斥锁,代码是什么”文章能对大家有所帮助。
目录
- 互斥锁
- 读写互斥锁
先来看这样一段代码,所存在的问题:
var wg sync.WaitGroup var x int64 func main() { wg.Add(2) go f() go f() wg.Wait() fmt.Println(x) // 输出:12135 } func f() { for i:=0; i10000; i++ { x = x+1 } wg.Done() }
这里为什么输出是 12135(不同的机器结果不一样),而不是20000。
因为 x 的赋值,总共分为三个步骤:取出x的值、计算x的结果、给x赋值。那么由于对于f函数的调用采用了goroutine协程,所以存在资源竞争的问题,所以有赋值和计算过程中存在脏数据。对于此类的问题,可以采用互斥锁解决:
互斥锁
互斥锁是一种常用的控制共享资源访问的方法,它能够保证同时只有一个goroutine可以访问共享资源。Go语言中使用sync包的Mutex类型来实现互斥锁。
var wg sync.WaitGroup var x int64 var lock sync.Mutex func main() { wg.Add(2) go f() go f() wg.Wait() fmt.Println(x) // 输出:20000 } func f() { for i:=0; i10000; i++ { lock.Lock() // 加互斥锁 x = x+1 lock.Unlock() // 解锁 } wg.Done() }
使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待锁;当互斥锁释放后,等待的goroutine才可以获取锁进入临界区,多个goroutine同时等待一个锁时,唤醒的策略是随机的。
读写互斥锁
互斥锁是完全互斥的,但是有很多实际的场景下是读多写少的,当我们并发的去读取一个资源不涉及资源修改的时候是没有必要加锁的,这种场景下使用读写锁是更好的一种选择。读写锁在Go语言中使用sync包中的RWMutex类型。
读写锁分为两种:读锁和写锁。当一个goroutine获取读锁之后,其他的goroutine如果是获取读锁会继续获得锁,如果是获取写锁就会等待;当一个goroutine获取写锁之后,其他的goroutine无论是获取读锁还是写锁都会等待。
var ( x1 int64 wg1 sync.WaitGroup lock1 sync.Mutex rwlock sync.RWMutex ) func main() { startTime := time.Now() for i:=0; i100; i++ { wg1.Add(1) write() } for i:=0; i10000; i++ { wg1.Add(1) read() } wg1.Wait() fmt.Println(time.Now().Sub(startTime)) // 互斥锁用时: 973.9304ms // 读写互斥锁用时: 718.094ms } func read() { defer wg1.Done() //lock1.Lock() // 互斥锁 rwlock.RLock() // 读写互斥锁 fmt.Println(x1) //lock1.Unlock() // 互斥锁 rwlock.RUnlock() // 读写互斥锁 } func write() { defer wg1.Done() lock1.Lock() x1 = x1+1 lock1.Unlock() }
以上就是关于“用Go语言怎么样实现互斥锁,代码是什么”的介绍了,感谢各位的阅读,希望文本对大家有所帮助。如果想要了解更多知识,欢迎关注网络,小编每天都会为大家更新不同的知识。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 用Go语言怎么样实现互斥锁,代码是什么
本文地址: https://pptw.com/jishu/653598.html