mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-08-11 01:22:36 +00:00
第9章,部分字词修订。
This commit is contained in:
@@ -102,7 +102,7 @@ func Withdraw(amount int) bool {
|
||||
|
||||
上面这个例子中,Deposit会调用mu.Lock()第二次去获取互斥锁,但因为mutex已经锁上了,而无法被重入(译注:go里没有重入锁,关于重入锁的概念,请参考java)--也就是说没法对一个已经锁上的mutex来再次上锁--这会导致程序死锁,没法继续执行下去,Withdraw会永远阻塞下去。
|
||||
|
||||
关于Go的互斥量不能重入这一点我们有很充分的理由。互斥量的目的是为了确保共享变量在程序执行时的关键点上能够保证不变性。不变性的其中之一是“没有goroutine访问共享变量”。但实际上对于mutex保护的变量来说,不变性还包括其它方面。当一个goroutine获得了一个互斥锁时,它会断定这种不变性能够被保持。其获取并保持锁期间,可能会去更新共享变量,这样不变性只是短暂地被破坏。然而当其释放锁之后,它必须保证不变性已经恢复原样。尽管一个可以重入的mutex也可以保证没有其它的goroutine在访问共享变量,但这种方式没法保证这些变量额外的不变性。(译注:这段翻译有点晕)
|
||||
关于Go的互斥量不能重入这一点我们有很充分的理由。互斥量的目的是为了确保共享变量在程序执行时的关键点上能够保证不变性。不变性的其中之一是“没有goroutine访问共享变量”。但实际上这里对于mutex保护的变量来说,不变性还包括其它方面。当一个goroutine获得了一个互斥锁时,它会断定这种不变性能够被保持。在其获取并保持锁期间,可能会去更新共享变量,这样不变性只是短暂地被破坏。然而当其释放锁之后,它必须保证不变性已经恢复原样。尽管一个可以重入的mutex也可以保证没有其它的goroutine在访问共享变量,但这种方式没法保证这些变量额外的不变性。(译注:这段翻译有点晕)
|
||||
|
||||
一个通用的解决方案是将一个函数分离为多个函数,比如我们把Deposit分离成两个:一个不导出的函数deposit,这个函数假设锁总是会被保持并去做实际的操作,另一个是导出的函数Deposit,这个函数会调用deposit,但在调用前会先去获取锁。同理我们可以将Withdraw也表示成这种形式:
|
||||
|
||||
@@ -134,6 +134,6 @@ func Balance() int {
|
||||
func deposit(amount int) { balance += amount }
|
||||
```
|
||||
|
||||
当然,这里的存款deposit函数很小实际上取款withdraw函数不需要理会对它的调用,尽管如此,这里的表达还是表明了规则。
|
||||
当然,这里的存款deposit函数很小,实际上取款Withdraw函数不需要理会对它的调用,尽管如此,这里的表达还是表明了规则。
|
||||
|
||||
封装(§6.6), 用限制一个程序中的意外交互的方式,可以使我们获得数据结构的不变性。因为某种原因,封装还帮我们获得了并发的不变性。当你使用mutex时,确保mutex和其保护的变量没有被导出(在go里也就是小写,且不要被大写字母开头的函数访问啦),无论这些变量是包级的变量还是一个struct的字段。
|
||||
|
Reference in New Issue
Block a user