返回
通道实现一个公平锁
后端
2024-01-21 05:52:43
通道实现公平锁
公平锁是一种计算机锁,它确保等待锁定的线程按先来先服务的原则获得锁。公平锁在多线程编程中很有用,因为它可以防止线程饥饿。
公平锁可以通过通道来实现。通道是一个用于 goroutine 之间通信的管道。它是一个 FIFO(先进先出)队列,goroutine 可以向通道发送数据,也可以从通道接收数据。
公平锁的实现如下:
package main
import (
"fmt"
"sync"
)
// 锁类型
type Mutex struct {
// 通道,用于实现锁
lock chan struct{}
// 互斥锁,用于防止其他 goroutine 修改锁的状态
mutex sync.Mutex
}
// 新建锁
func NewMutex() *Mutex {
// 创建一个容量为 1 的通道
lock := make(chan struct{}, 1)
// 加锁
lock <- struct{}{}
// 返回锁
return &Mutex{
lock: lock,
mutex: sync.Mutex{},
}
}
// 锁定
func (m *Mutex) Lock() {
// 互斥锁防止其他 goroutine 修改锁的状态
m.mutex.Lock()
defer m.mutex.Unlock()
// 从通道中接收数据,直到收到数据
<-m.lock
}
// 解锁
func (m *Mutex) Unlock() {
// 互斥锁防止其他 goroutine 修改锁的状态
m.mutex.Lock()
defer m.mutex.Unlock()
// 向通道发送数据
m.lock <- struct{}{}
}
func main() {
// 创建锁
mutex := NewMutex()
// 创建多个 goroutine,每个 goroutine 尝试获取锁
for i := 0; i < 10; i++ {
go func(i int) {
// 加锁
mutex.Lock()
fmt.Printf("Goroutine %d acquired the lock\n", i)
// 保持锁一段时间
time.Sleep(time.Second)
// 解锁
mutex.Unlock()
}(i)
}
// 等待所有 goroutine 完成
time.Sleep(11 * time.Second)
}
在上面的代码中,我们首先创建了一个 Mutex 类型的锁。然后,我们创建了 10 个 goroutine,每个 goroutine 都尝试获取锁。当一个 goroutine 获取锁后,它会休眠一秒钟,然后释放锁。
通过这种方式,我们可以模拟一个公平锁。当一个 goroutine 获取锁后,其他 goroutine 将无法获取锁,直到第一个 goroutine 释放锁。
总结
公平锁是一种很有用的工具,它可以防止线程饥饿。公平锁可以通过通道来实现。上面的代码演示了如何使用通道实现公平锁。