Go语言互斥锁
Posted Go程序员开发
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言互斥锁相关的知识,希望对你有一定的参考价值。
Go语言互斥锁
Go语言的sync包中实现了两种锁 Mutex (互斥锁)和 RWMutex (读写锁),其中 RWMutex 是基于 Mutex 实现的,只读锁的实现使用类似引用计数器的功能。
互斥锁
Mutex 是互斥锁,有 Lock()加锁、Unlock()解锁两个方法,使用Lock()加锁后,便不能再次对其进行加锁,直到利用 Unlock()解锁对其解锁后才能再次加锁。适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁也叫做全局锁。
func (m *Mutex) Lock()
Lock方法锁住m,如果m已经加锁,则阻塞直到m解锁。
func (m *Mutex) Unlock()
Unlock方法解锁m,如果m未加锁会导致运行时错误。锁和线程无关,可以由不同的线程加锁和解锁。
互斥锁应用
只要有两个goroutine并发访问同一变量,且至少其中的一个是写操作的时候就会发生数据竞争。数据竞争会在两个以上的goroutine并发访问相同的变量且至少其中一个为写操作时发生。
允许多个goroutine访问变量,但是同一时间只允许一个goroutine访问。我们可以用sync包中的Mutex来实现,保证共享变量不会被并发访问。
实例如下:
package main
import (
"fmt"
"sync"
)
var (
m = make(map[int]int)
Mlock = new(sync.Mutex)
)
func main() {
for i := 0; i < 1000; i++ {
go func(i int) {
// Mlock.Lock()
m[i] = i * i
// Mlock.Unlock()
}(i)
}
// Mlock.Lock()
for k, v := range m {
fmt.Printf("%d * %d = %d\n", k, k, v)
}
// Mlock.Unlock()
}
运行错误:
fatal error: concurrent map writes
将上述代码中的注释打开则程序正常运行。
当Unlock()在Lock()之前使用时便会报错,实例如下:
package main
import (
"fmt"
"sync"
)
func main() {
var MLock *sync.Mutex
MLock = new(sync.Mutex)
MLock.Unlock()
fmt.Println("hello Mutex")
MLock.Lock()
}
运行错误:
panic: sync: unlock of unlocked mutex
当在解锁之前再次进行加锁,便会死锁状态,实例如下:
package main
import (
"fmt"
"sync"
)
func main() {
var MLock *sync.Mutex
MLock = new(sync.Mutex)
MLock.Lock()
fmt.Println("hello Mutex")
MLock.Lock()
}
运行错误:
fatal error: all goroutines are asleep - deadlock!
互斥锁只能锁定一次,当在解锁之前再次进行加锁,便会死锁状态,如果在加锁前解锁,便会报错“panic: sync: unlock of unlocked mutex”。
下一篇:
Go语言读写锁------敬请期待!
第十一章 并发编程
11.1
11.2
11.3
11.4
第十二章 反射
12.1
12.2
第十三章 数据格式
13.1
13.2
第十四章 终端读取
14.1
14.2
第十五章 文件操作
15.1
15.2
15.3
15.4
15.5
15.6
第十六章 事件处理
16.1
16.2
16.3
自2017年6月起,老男孩IT教育就顺应技术发展潮流开设了Go语言开发课程,以帮助更多有需要的盆友们提升技能,若是想要了解具体课程内容的话,那就点击本文左下方“阅读原文”来咨询吧~
看完本文有收获?那就分享给更多人吧
万水千山总是情,点个 “好看” 行不行
以上是关于Go语言互斥锁的主要内容,如果未能解决你的问题,请参考以下文章
45. sync.Mutex 互斥和互斥锁 | 厚土Go学习笔记
go语言学习笔记 — 进阶 — 并发编程:互斥锁(sync.Mutex)—— 保证同时只有一个goroutine可以访问共享资源