以下是如何使用互斥锁以安全访问数据的示例。我的问题是如何使用CSP(通信顺序进程)而不是使用互斥锁和解锁来做同样的事情?
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
}
答案 0 :(得分:1)
如果你真的要看看Go如何实现通道,你基本上会看到一个数组周围的互斥锁,并带有一些额外的线程处理来阻止执行,直到值传递完毕。通道的工作是将数据从内存中的一个位置轻松移动到另一个位置。因此,在你有锁和解锁的地方,你会有这样的例子:
func example() {
resChan := make(int chan)
go func(){
resChan <- 1
}()
go func(){
res := <-resChan
}
}
因此,在示例中,第一个goroutine在发送值后被阻止,直到第二个goroutine从通道读取。
要使用互斥锁执行此操作,可以使用sync.WaitGroup,它将在设置值时向组中添加一个,然后从组中释放它,第二个goroutine将锁定然后解锁该值。
你的例子中的奇怪之处是1没有goroutines,所以它都发生在一个主要的goroutine中,并且锁被更传统地使用(如在c线程中那样),因此通道不会真正完成任何事情。您拥有的示例将被视为反模式,例如golang谚语说“不要通过共享内存进行通信,通过通信共享内存。”