使用互斥锁(Mutex)
- 原理:互斥锁用于保证在同一时间只有一个Goroutine能够访问共享资源,从而避免竞争条件。在银行转账场景中,账户余额就是共享资源。
- 代码实现:
package main
import (
"fmt"
"sync"
)
// Account 定义账户结构体
type Account struct {
balance int
mutex sync.Mutex
}
// Withdraw 从账户中取款
func (a *Account) Withdraw(amount int) {
a.mutex.Lock()
defer a.mutex.Unlock()
if a.balance >= amount {
a.balance -= amount
}
}
// Deposit 向账户中存款
func (a *Account) Deposit(amount int) {
a.mutex.Lock()
defer a.mutex.Unlock()
a.balance += amount
}
func transfer(from, to *Account, amount int, wg *sync.WaitGroup) {
defer wg.Done()
from.Withdraw(amount)
to.Deposit(amount)
}
func main() {
var wg sync.WaitGroup
account1 := &Account{balance: 1000}
account2 := &Account{balance: 2000}
// 模拟转账
for i := 0; i < 10; i++ {
wg.Add(1)
go transfer(account1, account2, 100, &wg)
}
wg.Wait()
fmt.Printf("Account1 balance: %d\n", account1.balance)
fmt.Printf("Account2 balance: %d\n", account2.balance)
}
使用通道(Channel)
- 原理:通道可以用于在Goroutine之间传递数据,并且保证数据传递的顺序性和原子性。我们可以通过通道来控制对账户余额的访问,从而避免竞争条件。
- 代码实现:
package main
import (
"fmt"
"sync"
)
// Account 定义账户结构体
type Account struct {
balance int
ch chan int
}
// Withdraw 从账户中取款
func (a *Account) Withdraw(amount int) {
a.ch <- 1
if a.balance >= amount {
a.balance -= amount
}
<-a.ch
}
// Deposit 向账户中存款
func (a *Account) Deposit(amount int) {
a.ch <- 1
a.balance += amount
<-a.ch
}
func transfer(from, to *Account, amount int, wg *sync.WaitGroup) {
defer wg.Done()
from.Withdraw(amount)
to.Deposit(amount)
}
func main() {
var wg sync.WaitGroup
account1 := &Account{balance: 1000, ch: make(chan int, 1)}
account2 := &Account{balance: 2000, ch: make(chan int, 1)}
// 模拟转账
for i := 0; i < 10; i++ {
wg.Add(1)
go transfer(account1, account2, 100, &wg)
}
wg.Wait()
fmt.Printf("Account1 balance: %d\n", account1.balance)
fmt.Printf("Account2 balance: %d\n", account2.balance)
}