互斥锁
互斥锁是传统并发编程中对共享资源进行访问控制的主要手段,它由标准库sync中的Mutex结构体类型表示。sync.Mutex类型只有两个公开的指针方法,Lock和Unlock。Lock锁定当前的共享资源,Unlock进行解锁。
- demo
在使用前通过Lock上锁,使用后能过Unlock解锁。
var count = 0
var wg sync.WaitGroup
var mutex sync.Mutex
func test() {
mutex.Lock()
count++
fmt.Println("the count is:", count)
time.Sleep(time.Millisecond*2)
mutex.Unlock()
wg.Done()
}
func main() {
for r := 0; r < 20; r++ {
wg.Add(1)
go test()
}
wg.Wait()
}
- 通过-race build查看资源竞争,再执行exe对比
go build -race main.go
main.exe
发现未加锁之前有报错,协程之间存在竞争关系
- demo2
可以关闭下面的互斥锁后,观察它们的变化
var count = 0
var wg sync.WaitGroup
var mutex sync.Mutex
var m = make(map[int]int, 0)
func test(num int) {
mutex.Lock()
var sum int = 1
for i := 1; i <= num; i++ {
sum *= i
}
m[num] = sum
fmt.Printf("key=%v value=%v\n", num, sum)
time.Sleep(time.Millisecond * 2)
mutex.Unlock()
wg.Done()
}
func main() {
for r := 0; r < 40; r++ {
wg.Add(1)
go test(r)
}
wg.Wait()
}
读写互斥锁
读取的时候,可以并发地访问;但写得时候,同一时刻只允许一人操作。
也就是说,当一个goruntine进行写操作时,其他goruntine既不能进行读操作,也不能进行写操作。
Go中的读写锁由结构体类型sync.RWMutex表示。它包含了两对方法:一组是对写操作的锁定和解锁,简称“写锁定”和“写解锁”
func (*RWMutex) Lock()
func (*RWMutex) Unlock()
另一组表示对读操作的锁定和解锁,简称“读锁定”与“读解锁”
func (*RWMutex) RLock()
func (*RWMutex) RUnlock()
- 写操作时互斥,读操作时并行
var count = 0
var wg sync.WaitGroup
var mutex sync.RWMutex
var m = make(map[int]int, 0)
func write(){
mutex.Lock()
fmt.Println("执行写操作")
time.Sleep(time.Second * 2)
mutex.Unlock()
wg.Done()
}
func read(){
mutex.RLock()
fmt.Println("执行读操作---")
//time.Sleep(time.Millisecond * 50)
mutex.RUnlock()
wg.Done()
}
func main() {
//开启10个协程执行读操作
for i := 0; i < 10; i++{
wg.Add(1)
go write()
}
//开启10个协程执行写操作
for i := 0; i < 10; i++ {
wg.Add(1)
go read()
}
wg.Wait()
}
执行写操作
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行写操作
//执行写操作
//……
网友评论