在Go语言中,常见的用于同步和并发控制的锁有以下几种:
- 互斥锁(
sync.Mutex
):用于保护共享数据不被并发的goroutine访问。 - 读写锁(
sync.RWMutex
):优先允许读操作,在写操作时阻塞所有其他goroutine。 - 条件变量(
sync.Cond
):与互斥锁一起使用,可以阻塞一个或多个goroutine,直到满足特定条件。 - 计数信号量(
sync.WaitGroup
):用于等待一组goroutine完成。 - 原子操作(
sync/atomic
包):对基本数据类型进行无锁的原子操作。
下面是这些锁的简单使用示例:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
// 互斥锁示例
var mutex sync.Mutex
mutex.Lock()
go func() {
mutex.Lock()
fmt.Println("Mutex locked")
time.Sleep(time.Second)
mutex.Unlock()
}()
time.Sleep(500 * time.Millisecond)
mutex.Unlock()
fmt.Println("Mutex unlocked")
// 读写锁示例
var rwMutex sync.RWMutex
go func() {
rwMutex.Lock()
fmt.Println("Write lock acquired")
time.Sleep(time.Second)
rwMutex.Unlock()
}()
time.Sleep(500 * time.Millisecond)
rwMutex.RLock()
fmt.Println("Read lock acquired")
rwMutex.RUnlock()
// 条件变量示例
var condVar sync.Cond
condVar.L = new(sync.Mutex)
go func() {
condVar.L.Lock()
fmt.Println("Waiting for signal")
condVar.Wait()
fmt.Println("Received signal")
condVar.L.Unlock()
}()
time.Sleep(1 * time.Second)
condVar.Signal()
// 计数信号量示例
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
fmt.Println("Worker 1 starting")
time.Sleep(time.Second)
fmt.Println("Worker 1 finished")
}()
go func() {
defer wg.Done()
fmt.Println("Worker 2 starting")
time.Sleep(2 * time.Second)
fmt.Println("Worker 2 finished")
}()
wg.Wait()
fmt.Println("All workers finished")
}
这段代码展示了互斥锁、读写锁、条件变量和计数信号量的基本使用方法。互斥锁用于保持数据的完整性,读写锁优先允许读操作,防止写操作阻塞所有读操作,条件变量可以让一个goroutine在满足特定条件前等待,计数信号量用于同步一组goroutine的完成。