互斥锁
定义
当多个goroutine
同时访问一个资源的时候需要加上互斥锁防止出错。互斥锁能保证同时只有一个goroutine
访问共享资源。Go语言中使用sync
包的Mutex
类型诗选互斥锁。
// Go语言中对 Mutex 的定义
// A Mutex is a mutual exclusion lock.
// The zero value for a Mutex is an unlocked mutex.
//
// A Mutex must not be copied after first use.
type Mutex struct {
state int32
sema uint32
}
举例
package main
import (
"fmt"
"sync"
)
var (
lock sync.Mutex
wg sync.WaitGroup
x = 0
)
func add() {
for i := 0; i < 500000; i++ {
lock.Lock() // 上锁
x++
lock.Unlock() // 解锁
}
wg.Done()
}
func main() {
wg.Add(2)
go add()
go add()
wg.Wait()
fmt.Println(x)
}
使用互斥锁能保证同一时间有且只有一个goroutine
进入临界区,其他的goroutine
则在等待锁;当互斥锁释放后,等待的goroutine
才可以获取锁进入临界区。多个goroutine
同时等待一个锁时,唤醒的策略是随机的。
读写互斥锁
互斥锁是完全互斥的,当我们并发的去读取一个资源不涉及资源修改的时候是没有必要加锁的,读取远远大于写的时候使用读写锁。读写锁在Go语言中使用sync
包中的RWMutex
类型。
举例:
package main
import (
"fmt"
"sync"
"time"
)
var (
x int64
wg sync.WaitGroup
lock sync.Mutex
rwlock sync.RWMutex
)
func write() {
// lock.Lock() // 加互斥锁
rwlock.Lock() // 加写锁
x = x + 1
time.Sleep(10 * time.Millisecond) // 假设读操作耗时10毫秒
rwlock.Unlock() // 解写锁
// lock.Unlock() // 解互斥锁
wg.Done()
}
func read() {
// lock.Lock() // 加互斥锁
rwlock.RLock() // 加读锁
time.Sleep(time.Millisecond) // 假设读操作耗时1毫秒
rwlock.RUnlock() // 解读锁
// lock.Unlock() // 解互斥锁
wg.Done()
}
func main() {
start := time.Now()
for i := 0; i < 10; i++ {
wg.Add(1)
go write()
}
for i := 0; i < 10000; i++ {
wg.Add(1)
go read()
}
wg.Wait()
end := time.Now()
fmt.Println(end.Sub(start))
}
![](https://i-blog.csdnimg.cn/blog_migrate/eb3506142f415f208696cbad3c9ee884.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4ac2c300e3bd72199119992ff3125e98.png)