Go语言并发编程中Mutex有几种状态
Go语言并发编程中Mutex有几种状态
mutexLocked — 表示互斥锁的锁定状态; mutexWoken — 表示从正常模式被从唤醒; mutexStarving — 当前的互斥锁进入饥饿状态; waitersCount — 当前互斥锁上等待的 Goroutine 个数;
在Go语言的并发编程中,sync.Mutex
是用来保护共享资源不被多个goroutine同时访问的重要工具。虽然 sync.Mutex
的内部实现细节对外部是隐藏的,以提供简洁和安全的抽象,但从功能的角度,我们可以将其状态大致分为以下几种:
-
解锁(Unlocked):这是
sync.Mutex
的默认状态,表示没有任何goroutine持有该互斥锁,任何尝试加锁的goroutine都可以成功获取锁并进入临界区。 -
锁定(Locked):当某个goroutine成功调用
Lock()
方法后,sync.Mutex
进入锁定状态,表示当前有且仅有一个goroutine持有该锁,其他尝试加锁的goroutine将会被阻塞,直到锁被释放。 -
饥饿(理论上不存在显式状态,但属于行为特性):虽然
sync.Mutex
没有直接的“饥饿”状态,但长时间的锁争用可能导致某些goroutine长时间等待而无法获取锁,这种情况被称为“饥饿”。Go 1.9 版本之后,sync.Mutex
实现了自旋锁(spinlock)来减少锁的延迟,并可能包含公平性机制(如Go 1.18中引入的公平锁尝试),以减少饥饿情况的发生。
示例代码
下面是一个简单的示例,展示如何在Go中使用 sync.Mutex
来保护共享资源:
package main
import (
"fmt"
"sync"
"time"
)
var (
counter int
mu sync.Mutex
)
func increment(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
counter++
fmt.Println("Counter:", counter)
mu.Unlock()
// 模拟耗时操作
time.Sleep(time.Millisecond * 100)
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait()
fmt.Println("Final counter:", counter)
}
在上面的代码中,counter
是一个被多个goroutine共享的变量,通过 sync.Mutex
mu
来保证每次只有一个goroutine能够修改 counter
的值。
注意,由于 sync.Mutex
的具体实现(包括其内部状态)可能会随着Go语言的版本更新而变化,因此上面的“状态”分类主要是为了理解和讨论的目的,而不是基于 sync.Mutex
的内部实现细节。