Go 中的锁
Go 语言提供了多种锁机制,用于在并发编程中保护共享资源。常见的锁包括 互斥锁、读写锁 和 sync.Map 的安全锁。
1. 互斥锁(Mutex)
原理
互斥锁(sync.Mutex
)是一种最简单的锁机制,用于保护共享资源的独占访问。当一个 Goroutine 获取了互斥锁后,其他 Goroutine 必须等待锁释放才能访问共享资源。
特点
- 独占访问:同一时间只有一个 Goroutine 可以持有锁。
- 阻塞等待:未获取锁的 Goroutine 会阻塞,直到锁被释放。
- 简单易用:适用于简单的临界区保护。
使用场景
- 适用于对共享资源的独占访问场景。
- 适用于临界区较小的场景。
2. 读写锁(RWMutex)
原理
读写锁(sync.RWMutex
)是一种更高效的锁机制,允许多个 Goroutine 同时读取共享资源,但只允许一个 Goroutine 写入共享资源。
特点
- 读共享:多个 Goroutine 可以同时获取读锁。
- 写独占:只有一个 Goroutine 可以获取写锁,且写锁与读锁互斥。
- 高效并发:适用于读多写少的场景。
使用场景
- 适用于读操作远多于写操作的场景。
- 适用于需要高并发读取共享资源的场景。
3. sync.Map 的安全锁
原理
sync.Map
是 Go 语言提供的一种并发安全的映射类型,内部通过锁机制和分段存储实现高效的并发访问。
特点
- 并发安全:无需额外加锁即可安全地并发访问。
- 高效读写:通过分段锁和原子操作优化性能。
- 动态扩展:支持动态扩展存储空间。
使用场景
- 适用于需要高并发读写的映射场景。
- 适用于键值对数量动态变化的场景。
以下是 Go 语言中三种锁的工作原理流程图:
三种锁使用实例
互斥锁
package main
import (
"fmt"
"sync"
"time"
)
var (
counter int
mutex sync.Mutex
)
func increment() {
mutex.Lock() // 加锁
counter++
mutex.Unlock() // 解锁
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
increment()
}()
}
wg.Wait()
fmt.Println("Final Counter Value:", counter)
}
Final Counter Value: 1000
读写锁(RWMutex)
package main
import (
"fmt"
"sync"
"time"
)
var (
data map[string]string
rwMutex sync.RWMutex
)
func readData(key string) string {
rwMutex.RLock() // 加读锁
defer rwMutex.RUnlock() // 解读锁
return data[key]
}
func writeData(key, value string) {
rwMutex.Lock() // 加写锁
defer rwMutex.Unlock() // 解写锁
data[key] = value
}
func main() {
data = make(map[string]string)
var wg sync.WaitGroup
// 写操作
wg.Add(1)
go func() {
defer wg.Done()
writeData("name", "Alice")
}()
// 读操作
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Name:", readData("name"))
}()
wg.Wait()
}
Name: Alice
sync.Map 的安全锁
package main
import (
"fmt"
"sync"
)
func main() {
var sm sync.Map
// 存储数据
sm.Store("name", "Alice")
sm.Store("age", 30)
// 读取数据
if value, ok := sm.Load("name"); ok {
fmt.Println("Name:", value)
}
// 遍历数据
sm.Range(func(key, value interface{}) bool {
fmt.Printf("Key: %v, Value: %v\n", key, value)
return true
})
}
Name: Alice
Key: name, Value: Alice
Key: age, Value: 30