^_^

2010年2月4日星期四

Go 语言 buffered/unbuffered channel 辨析

Case one:

Test code:
package main

import (
 "time" 
 "fmt"
 "flag"
)

var unbufferedChannel = flag.Bool("u", true, "unbuffered channel")

func main() {
 flag.Parse()
 count := 0
 if *unbufferedChannel {
  count = 0
  fmt.Printf("unbuffered channel\n")
 } else {
  count = 1
  fmt.Printf("buffered channel\n")
 }
 c := make(chan string, count)
 go func() {
      doInFunc(1)
      c <- "done"
  fmt.Printf("%v func return\n", time.LocalTime())
 }()
 doInMain(2)
 <-c
 fmt.Printf("%v main return\n", time.LocalTime())
}

func doInMain(sec int) {
 fmt.Printf("%v begin doInMain()\n", time.LocalTime())
 time.Sleep((int64)(sec*1e9))
 fmt.Printf("%v end doInMain()\n", time.LocalTime())
}

func doInFunc(sec int) {
 fmt.Printf("%v begin doInFunc()\n", time.LocalTime())
 time.Sleep((int64)(sec*1e9))
 fmt.Printf("%v end doInFunc()\n", time.LocalTime())
}
Run Result:
root001@ubuntu001:~/foolbear$ ./testch.out -u=false
buffered channel
Thu Feb  4 12:55:24 CST 2010 begin doInMain()
Thu Feb  4 12:55:24 CST 2010 begin doInFunc()
Thu Feb  4 12:55:25 CST 2010 end doInFunc()
Thu Feb  4 12:55:25 CST 2010 func return
Thu Feb  4 12:55:26 CST 2010 end doInMain()
Thu Feb  4 12:55:26 CST 2010 main return
root001@ubuntu001:~/foolbear$ ./testch.out
unbuffered channel
Thu Feb  4 13:03:24 CST 2010 begin doInMain()
Thu Feb  4 13:03:24 CST 2010 begin doInFunc()
Thu Feb  4 13:03:25 CST 2010 end doInFunc()
Thu Feb  4 13:03:26 CST 2010 end doInMain()
Thu Feb  4 13:03:26 CST 2010 main return
Thu Feb  4 13:03:26 CST 2010 func return
注意上面测试结果的输出时序,对比 buffered/unbuffered channel 的不同逻辑。

总结:
Receivers always block until there is data to receive. If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.

Case two:

Test code:
package main

import (
 "time" 
 "fmt"
)

const (
 requestCount = 4
 concurrentCount = 2
)

var sem = make(chan int, concurrentCount)
var done = make(chan int, requestCount)

func handle(index int) {
 sem <- 1
 fmt.Printf("[%d]%v job begin\n", index, time.LocalTime())
 time.Sleep((int64)(2*1e9))
 <- sem
 done <- 0
 fmt.Printf("[%d]%v handle return\n", index, time.LocalTime())
}

func Serve() {
 for index := 0; index < requestCount; index ++ {
  go handle(index)
 }
 for index := 0; index < requestCount; index ++ {
  <- done
 }
}

func main() {
 Serve()
 fmt.Printf("%v main return, 全部结束了\n", time.LocalTime())
}
Run Result:
[0]Thu Feb  4 16:46:09 CST 2010 job begin
[1]Thu Feb  4 16:46:09 CST 2010 job begin
[0]Thu Feb  4 16:46:11 CST 2010 handle return
[1]Thu Feb  4 16:46:11 CST 2010 handle return
[2]Thu Feb  4 16:46:11 CST 2010 job begin
[3]Thu Feb  4 16:46:11 CST 2010 job begin
[2]Thu Feb  4 16:46:13 CST 2010 handle return
[3]Thu Feb  4 16:46:13 CST 2010 handle return
Thu Feb  4 16:46:13 CST 2010 main return, 全部结束了
总结:
A buffered channel can be used like a semaphore, for instance to limit throughput. In this example, incoming requests are passed to handle, which sends a value into the channel, processes the request, and then receives a value from the channel. The capacity of the channel buffer limits the number of simultaneous calls to process.
FYI:
本站文章除注明外,均为本站原创
转载请注明文章转载自: 大笨熊乐园 [ https://blog.foolbear.com/ ]
文章标题: Go 语言 buffered/unbuffered channel 辨析
文章地址: https://blog.foolbear.com/2010/02/go-bufferedunbuffered-channel.html

1 条评论 :

匿名 说...

Hi there to every one, the contents existing at this
web page are truly remarkable for people experience, well, keep up the good work fellows.


Take a look at my web site ... Cheap Louis Vuitton

发表评论

Related Posts with Thumbnails