【发布时间】:2016-10-19 14:10:29
【问题描述】:
以下是如何使用互斥锁来安全访问数据的示例。我将如何使用 CSP (communication sequential processes) 而不是使用互斥锁和解锁来做同样的事情?
type Stack struct {
top *Element
size int
sync.Mutex
}
func (ss *Stack) Len() int {
ss.Lock()
size := ss.size
ss.Unlock()
return size
}
func (ss *Stack) Push(value interface{}) {
ss.Lock()
ss.top = &Element{value, ss.top}
ss.size++
ss.Unlock()
}
func (ss *SafeStack) Pop() (value interface{}) {
ss.Lock()
size := ss.size
ss.Unlock()
if size > 0 {
ss.Lock()
value, ss.top = ss.top.value, ss.top.next
ss.size--
ss.Unlock()
return
}
return nil
}
【问题讨论】:
-
这是一道作业题吗?您的代码似乎缺少部分内容,包括
Element的定义。 -
为什么?在这种情况下,互斥锁是正确的原语吗? (另外,使用
deferplay.golang.org/p/G-Y9sGooaQ 更简洁,更不容易出错) -
通道范式的全部目的是摆脱互斥体。使用通道,您可以在没有它们的情况下进行同步。但为了向您展示,我们需要您的实际代码,而不仅仅是锁定代码。通常为了有效地使用渠道,必须围绕它设计程序架构。你不能仅仅改变几行来有效地使用它们。
-
你的代码中有一个竞争条件——当你释放互斥锁来测试你的堆栈是否为空时,另一个 goroutine 可能会弹出最后一个元素。