又叫 “通过通信来共享内存”。
现在账号被命名为 ConcurrentAccount,像下面这样来实现:
type ConcurrentAccount struct {
account *SimpleAccount
deposits chan uint
withdrawals chan uint
balances chan chan int
}
func NewConcurrentAccount(amount int) *ConcurrentAccount{
acc := &ConcurrentAccount{
account : &SimpleAccount{balance: amount},
deposits: make(chan uint),
withdrawals: make(chan uint),
balances: make(chan chan int),
}
acc.listen()
return acc
}
func (acc *ConcurrentAccount) Balance() int {
ch := make(chan int)
acc.balances <- ch
return <-ch
}
func (acc *ConcurrentAccount) Deposit(amount uint) {
acc.deposits <- amount
}
func (acc *ConcurrentAccount) Withdraw(amount uint) {
acc.withdrawals <- amount
}
func (acc *ConcurrentAccount) listen() {
go func() {
for {
select {
case amnt := <-acc.deposits:
acc.account.Deposit(amnt)
case amnt := <-acc.withdrawals:
acc.account.Withdraw(amnt)
case ch := <-acc.balances:
ch <- acc.account.Balance()
}
}
}()
}
ConcurrentAccount 同样封装了 SimpleAccount ,然后增加了通信通道
调用代码和加锁版本的一样,这里就不写了,唯一不一样的就是初始化银行账号的时候:
b := NewBank(bank.NewConcurrentAccount(balance))
运行产生的结果和加锁版本一样:
初始化余额 80
[-] 30 马伊琍
[-] 10 姚笛
-----------------
剩余余额 40
让我们来深入了解一下细节。
通过通信来共享内存是如何工作的
一些基本注意点:
共享资源被封装在一个控制流程中。
结果就是资源成为了非共享状态。没有处理程序能够直接访问或者修改资源。你可以看到访问和修改资源的方法实际上并没有执行任何改变。
func (acc *ConcurrentAccount) Balance() int {
ch := make(chan int)
acc.balances <- ch
balance := <-ch
return balance
}










