面试题答案
一键面试设计思路
- Mutex锁:用于保护共享资源,如账户余额。在对账户余额进行更新等操作时,使用Mutex锁来确保同一时间只有一个goroutine可以访问和修改余额,防止竞态条件。
- Channel:用于在不同的goroutine之间传递数据和信号。例如,将交易请求通过Channel发送到专门处理交易的goroutine,避免直接在多个goroutine中同时操作共享资源。还可以利用Channel进行同步,比如一个goroutine完成某项任务后通过Channel通知其他goroutine。
- WaitGroup:用于等待一组goroutine完成。在系统启动多个goroutine处理交易等任务时,使用WaitGroup来阻塞主线程,直到所有相关的goroutine完成工作,确保系统在所有任务完成后再进行下一步操作,比如关闭资源等。
核心代码片段
package main
import (
"fmt"
"sync"
)
// 定义账户结构体
type Account struct {
balance int
mutex sync.Mutex
}
// 更新账户余额
func (a *Account) updateBalance(amount int) {
a.mutex.Lock()
a.balance += amount
a.mutex.Unlock()
}
// 获取账户余额
func (a *Account) getBalance() int {
a.mutex.Lock()
defer a.mutex.Unlock()
return a.balance
}
func main() {
var wg sync.WaitGroup
account := Account{}
// 模拟交易请求通道
transactionCh := make(chan int)
// 启动交易处理goroutine
go func() {
for amount := range transactionCh {
account.updateBalance(amount)
}
}()
// 模拟多个并发交易
numTransactions := 10
for i := 0; i < numTransactions; i++ {
wg.Add(1)
go func(amount int) {
defer wg.Done()
transactionCh <- amount
}(i * 10)
}
// 等待所有交易处理完成
go func() {
wg.Wait()
close(transactionCh)
}()
// 等待交易处理goroutine完成所有交易
wg.Wait()
// 获取最终账户余额
balance := account.getBalance()
fmt.Printf("Final balance: %d\n", balance)
}
在上述代码中:
Account
结构体包含余额和一个Mutex
锁,用于保护余额的更新操作。updateBalance
方法通过Mutex
锁确保余额更新的原子性。main
函数中创建了一个交易请求的Channel
,并启动一个goroutine来处理这些交易请求。- 使用
WaitGroup
来等待所有模拟的交易goroutine完成,完成后关闭Channel
,最终获取并打印账户的最终余额。