package main
import (
"fmt"
"sync"
)
// 定义银行账户结构体
type BankAccount struct {
balance int
mu sync.Mutex
rwmu sync.RWMutex
}
// 存款操作
func (b *BankAccount) Deposit(amount int, wg *sync.WaitGroup) {
defer wg.Done()
b.mu.Lock()
defer b.mu.Unlock()
b.balance += amount
fmt.Printf("Deposited %d. New balance: %d\n", amount, b.balance)
}
// 取款操作
func (b *BankAccount) Withdraw(amount int, wg *sync.WaitGroup) {
defer wg.Done()
b.mu.Lock()
defer b.mu.Unlock()
if b.balance >= amount {
b.balance -= amount
fmt.Printf("Withdrawn %d. New balance: %d\n", amount, b.balance)
} else {
fmt.Println("Insufficient funds")
}
}
// 查询余额操作
func (b *BankAccount) GetBalance(wg *sync.WaitGroup) {
defer wg.Done()
b.rwmu.RLock()
defer b.rwmu.RUnlock()
fmt.Printf("Current balance: %d\n", b.balance)
}
func main() {
var wg sync.WaitGroup
account := BankAccount{balance: 1000}
// 模拟多个用户存款
for i := 0; i < 3; i++ {
wg.Add(1)
go account.Deposit(100, &wg)
}
// 模拟多个用户取款
for i := 0; i < 2; i++ {
wg.Add(1)
go account.Withdraw(200, &wg)
}
// 模拟多个用户查询余额
for i := 0; i < 5; i++ {
wg.Add(1)
go account.GetBalance(&wg)
}
wg.Wait()
}
锁机制选择及性能影响
- 读多写少场景
- 选择:使用
sync.RWMutex
。因为读操作可以并发执行,多个读操作之间不会产生数据竞争,所以可以提高读操作的并发性能。
- 性能影响:读操作性能提升明显,因为多个读操作可以同时获取读锁,减少等待时间。而写操作需要获取写锁,写锁会排斥其他读锁和写锁,所以写操作的等待时间可能会增加,但由于写操作少,整体系统性能仍然会提升。
- 写多读少场景
- 选择:使用
sync.Mutex
。因为写操作多,如果使用 sync.RWMutex
,写操作获取写锁时会等待所有读锁释放,可能导致写操作等待时间过长。而 sync.Mutex
简单直接,无论是读操作还是写操作都只需要获取唯一的锁,虽然会降低并发度,但在写多读少的场景下,减少了锁的切换开销。
- 性能影响:虽然
sync.Mutex
降低了并发度,但避免了 sync.RWMutex
中读锁对写锁的阻塞,使得写操作可以更快地执行,整体性能会有所提升。如果使用 sync.RWMutex
在这种场景下,可能会因为写操作等待读锁释放而导致性能下降。