英文:
I don't understand the golang channel well
问题
close(e.ready) and <-e.ready are used to synchronize the goroutines in the memo package.
In the code you provided, close(e.ready) is called in the call method of the entry struct. This line of code is responsible for broadcasting the "ready" condition to all goroutines waiting on the e.ready channel. By closing the channel, it indicates that the result is ready and any goroutine waiting on this channel can proceed.
On the other hand, <-e.ready is called in the deliver method of the entry struct. This line of code is used to wait for the "ready" condition. When this line is executed, the goroutine will block until another goroutine closes the e.ready channel. Once the channel is closed, the goroutine will continue executing and send the result to the client through the response channel.
In summary, close(e.ready) is used to signal that the result is ready, and <-e.ready is used to wait for the result to be ready before proceeding. This synchronization mechanism ensures that the result is delivered to the client only when it is available.
英文:
Goroutines and channels are bothering me these days. I'm looking at the memo5 code at https://github.com/adonovan/gopl.io/tree/master/ch9.
If you look at memo.go of memo5, there are func (e *entry) call(f Func, key string) and func (e *entry) deliver(response chan<- result) parts.
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 278.
// Package memo provides a concurrency-safe non-blocking memoization
// of a function. Requests for different keys proceed in parallel.
// Concurrent requests for the same key block until the first completes.
// This implementation uses a monitor goroutine.
package memo
//!+Func
// Func is the type of the function to memoize.
type Func func(key string) (interface{}, error)
// A result is the result of calling a Func.
type result struct {
value interface{}
err error
}
type entry struct {
res result
ready chan struct{} // closed when res is ready
}
//!-Func
//!+get
// A request is a message requesting that the Func be applied to key.
type request struct {
key string
response chan<- result // the client wants a single result
}
type Memo struct{ requests chan request }
// New returns a memoization of f. Clients must subsequently call Close.
func New(f Func) *Memo {
memo := &Memo{requests: make(chan request)}
go memo.server(f)
return memo
}
func (memo *Memo) Get(key string) (interface{}, error) {
response := make(chan result)
memo.requests <- request{key, response}
res := <-response
return res.value, res.err
}
func (memo *Memo) Close() { close(memo.requests) }
//!-get
//!+monitor
func (memo *Memo) server(f Func) {
cache := make(map[string]*entry)
for req := range memo.requests {
e := cache[req.key]
if e == nil {
// This is the first request for this key.
e = &entry{ready: make(chan struct{})}
cache[req.key] = e
go e.call(f, req.key) // call f(key)
}
go e.deliver(req.response)
}
}
func (e *entry) call(f Func, key string) {
// Evaluate the function.
e.res.value, e.res.err = f(key)
// Broadcast the ready condition.
close(e.ready)
}
func (e *entry) deliver(response chan<- result) {
// Wait for the ready condition.
<-e.ready
// Send the result to the client.
response <- e.res
}
//!-monitor
I don't understand how close(e.ready) and <-e.ready synchronize here. Even after reading the book, I don't understand. Please tell me what the mechanism is.
答案1
得分: 1
e.ready更常被称为done通道。这是一种通过关闭done(e.ready通道)来告诉您的引用函数某个东西已经准备好的方法。<-e.ready将会阻塞,直到done(关闭)。
所以...阅读这段代码的意思是:
1)deliver等待准备好的信号。
2)call获取e.res的数据(e.res.value, e.res.err = f(key))。
3)call通过关闭它来释放done通道(close(e.ready))。
4)deliver可以通过从<-e.ready阻塞读取并将数据发送到response。
英文:
e.ready is more known as done channel. this is a way to tell your ref functions that domething is ready by closing done (e.ready chan). <-e.ready is going to block until its done (closed).
so... reading this code it means next.
deliverwaits for rediness signal.callgets data for e.res(e.res.value, e.res.err = f(key)`)callreleas done channel by closing it (close(e.ready))delivercan move throu block reading from<-e.readyand send data toresponse
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论