面试题答案
一键面试GoMutex确保并发环境下数据结构一致性和安全性的原理
- 互斥锁概念:Go语言中的
GoMutex
(通常指sync.Mutex
)是一种互斥锁,其核心作用是通过限制同一时间只有一个goroutine能够访问共享资源,从而避免多个goroutine同时修改数据导致的数据不一致问题。 - 工作机制:当一个goroutine调用
mutex.Lock()
方法时,如果锁当前未被其他goroutine持有,该goroutine将获得锁并可以访问共享资源。在访问完成后,它必须调用mutex.Unlock()
方法释放锁,以便其他goroutine有机会获取锁并访问共享资源。如果锁已被其他goroutine持有,调用Lock()
的goroutine将被阻塞,直到锁被释放。
使用GoMutex防止竞态条件的共享计数器示例
package main
import (
"fmt"
"sync"
)
// Counter 定义共享计数器结构体
type Counter struct {
value int
mutex sync.Mutex
}
// Increment 增加计数器的值
func (c *Counter) Increment() {
c.mutex.Lock()
c.value++
c.mutex.Unlock()
}
// GetValue 获取计数器的值
func (c *Counter) GetValue() int {
c.mutex.Lock()
defer c.mutex.Unlock()
return c.value
}
func main() {
var wg sync.WaitGroup
counter := Counter{}
// 启动10个goroutine来增加计数器的值
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Increment()
}()
}
// 等待所有goroutine完成
wg.Wait()
// 获取并打印计数器的值
fmt.Println("Final value:", counter.GetValue())
}
在上述代码中:
Counter
结构体包含一个int
类型的value
字段用于存储计数器的值,以及一个sync.Mutex
类型的mutex
字段用于保护对value
的访问。Increment
方法在修改value
之前调用mutex.Lock()
获取锁,修改完成后调用mutex.Unlock()
释放锁,确保同一时间只有一个goroutine可以修改value
。GetValue
方法同样在读取value
之前获取锁,读取完成后释放锁,防止读取过程中value
被其他goroutine修改。- 在
main
函数中,启动10个goroutine并发调用Increment
方法增加计数器的值,最后获取并打印计数器的最终值。通过使用sync.Mutex
,有效防止了竞态条件的发生,保证了数据的一致性和安全性。