Hi,
Yes, in general the program follows your thought line, but you have one
slight error in it:
When you send a number into the channel (i.e. line 11, c <- x), if there
is a reader on the other side, then both go routines are allowed to
continue. Thus one will be at "AFTER SET c" and the other inside the fmt.
But the order here is unspecified, as in the scheduler gets to choose which
to run and which to stop (or if you're running on multiple cores then they
can even run concurrently). This means, that you have no control over the
order of events (function calls) in two concurrent threads.
So when you're seeing "set c 1", "set c 1", get c 1" (or later "set c 5",
"set c 8", "get c 5") what actually is happening that:
1. Reader blocks on "<-c" while evaluating the arguments to fmt-"get c"
2. Writer prints first value "set c 1"
3. Writer sends in first value c <- 1
4. Writer would block, but reader can get it out, so it's not suspended
5. Reader got the "<-c", so is resumed
6. Here the scheduler has to make a decision: suspend the writer(fibbo
generator) and run the reader OR keep the reader suspended and continue
with the writer
7. The scheduler chose to allow the writer to continue
8. Writer prints "AFTER SET c"
9. Writer calculates new number
10. Writer prints second value "set c 1" (again number 1, remember the
sequence is 1, 1, 2, 3, 5, 8, ...)
11. Writer sends in second value c <- 1
12. Nobody to read the value, writer blocks
13. Scheduler has only the reader to allow, continues it thus
14. Reader got the first one and was suspended in the middle of fmt
argument evaluation, so it continues from there
15. Reader prints "set c 1" (this was the first 1)
16. Reader tries to get another number from c, and since the second 1 is
inside, it gets it
17. Now again, both are unblocked, scheduler has to choose
18. Etc.
The channel is the synchronization point. Your only guarantee is that
both threads will wait there for each other. Other than than, each thread
will happily race with the other in their doings.
Hope this clears it up a bit :)
Cheers,
Peter
On Wed, Apr 10, 2013 at 5:11 AM, lionkingfly wrote:nice peter, thanks.
Here are my understandings about the code. Please advice me if they are
right.
1. line 22, 23, create two goroutines (A goroutine - fibonacci and B
goroutine - func), immediately return to main thread, line 35, <-quit
makes block, quit channel is ready to receive value int. As main thread is
blocked, scheduler lets A goroutine run before B goroutine by the order of
creation.
2. line 11, send x to channel c(no buffer), makes block, (scheduler runs
main thread line 35, check quit channel but is still blocked, I'm not
sure about this) then run B goroutine.
3. line 26, <-c, as channel c is ready to be received, print its value,
then run to line 26 again, now <-c makes channel c block *but ready to
receive*, Run A gorountie, back to line 11(Need some check? or run to
line 12 directly?), print AFTER SET c, set c 1.
4. *main confusion is now,* line 11, send x(1) to channel c but no block
happened(because it's ready to receive, the value stored in channel c),
print AFTER SET c, set c 1, then again to line 11, again send x(1) to
channel c but currently block happened(How the channel do this? currently
where this value stored? cache but only change the status of the channel?)
...
于 2013/4/9 20:57, Péter Szilágyi 写道:
And what is your question? You have two threads, one producer and one
consumer communicating through a channel which you can follow with the
set/get pairs + some test outputs. Since your go routines are ran
concurrently (actually scheduled) you have a slight variance in the order
in which the texts between the two goroutines are displayed.
On Tue, Apr 9, 2013 at 12:05 PM, kingfly lion wrote:Dear All,
I modify the tour sample of channel(http://tour.golang.org/#66) to
confirm if the channel feature runs as i think.
But i'm not very sure.
Which friend can explain the output result?
*channel.go*
package main
import "fmt"
func fibonacci(c, quit chan int) {
fmt.Println("fibonacci start")
x, y := 0, 1
for {
fmt.Println("set c", x)
c <- x
fmt.Println("AFTER SET c")
x, y = y, x+y
}
fmt.Println("fibonacci end")
}
func main() {
c := make(chan int)
quit := make(chan int)
go fibonacci(c, quit)
go func() {
fmt.Println("func start")
for i := 0; i < 10; i++ {
fmt.Println("get c", <-c)
fmt.Println("AFTER GET c")
}
fmt.Println("func, outside for.")
fmt.Println(<-c)
quit <- 1
fmt.Println("func end")
}()
fmt.Println(<-quit)
}
*output:*
fibonacci start
set c 0
func start
get c 0
AFTER GET c
AFTER SET c
set c 1
AFTER SET c
set c 1
get c 1
AFTER GET c
get c 1
AFTER GET c
AFTER SET c
set c 2
AFTER SET c
set c 3
get c 2
AFTER GET c
get c 3
AFTER GET c
AFTER SET c
set c 5
AFTER SET c
set c 8
get c 5
AFTER GET c
get c 8
AFTER GET c
AFTER SET c
set c 13
AFTER SET c
set c 21
get c 13
AFTER GET c
get c 21
AFTER GET c
AFTER SET c
set c 34
AFTER SET c
set c 55
get c 34
AFTER GET c
func, outside for.
55
func end
AFTER SET c
set c 89
1
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit
https://groups.google.com/groups/opt_out. --
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit
https://groups.google.com/groups/opt_out.