GoLang之Concurrency协程goroutine使用方法
delphiwcdj · · 3385 次点击 · · 开始浏览2013年12月08日 wcdj
在go语言中,使用goroutine(a lightweight thread managed by the Go runtime)来实现并发程序。
go f(x, y, z)
starts a new goroutine running
f(x, y, z)
The evaluation of f, x, y, and z happens in the current goroutine and the execution off happens in the new goroutine.
Goroutines run in the same address space, so access to shared memory must be synchronized. Thesync package provides useful primitives, although you won't need them much
in Go as there are other primitives. (See the next slide, Channels.http://tour.golang.org/#64)
简单的测试用例:
package main
import (
"fmt"
"time"
)
func main() {
// A goroutine is a lightweight thread managed by the Go runtime
// Goroutines run in the same address space, so access to shared memory must be synchronized
go say("world")
say("hello")
fmt.Println("---------------1")
a := []int{7, 2, 8, -9, 4, 0}
// Channels are a typed conduit through which you can send and receive values with the channel operator, <-
// By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
fmt.Println("---------------2")
// Channels can be buffered. Provide the buffer length as the second argument to make to initialize a buffered channel
c2 := make(chan int, 2)
c2 <- 1
c2 <- 2
//c2 <- 3// error, the send buffer is full that will causes deadlock!
fmt.Println(<-c2)
fmt.Println(<-c2)
//fmt.Println(<-c2)// error, the receive buffer is empty that will causes deadlock too!
fmt.Println("---------------3")
c3 := make(chan int, 10)
go fibonacci(cap(c3), c3)
for i := range c3 {
fmt.Println(i)
}
fmt.Println("---------------4")
c4 := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c4)
}
quit <- 0
}()
fibonacci2(c4, quit)
fmt.Println("---------------5")
// The default case in a select is run if no other case is ready
// Use a default case to try a send or receive without blocking
tick := time.Tick(100 * time.Millisecond)
boom := time.After(500 * time.Millisecond)
for {
select {
case <-tick:
fmt.Println("tick. ")
case <-boom:
fmt.Println("BOOM!")
return
default:
fmt.Println(" .")
time.Sleep(50 * time.Millisecond)
}
}
}
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // send sum to c
}
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
// Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic
// Another note: Channels aren't like files; you don't usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop
close(c)
}
// The select statement lets a goroutine wait on multiple communication operations
// A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready
func fibonacci2(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
/*
output:
hello
world
hello
world
hello
world
hello
world
hello
---------------1
world
17 -5 12
---------------2
1
2
---------------3
0
1
1
2
3
5
8
13
21
34
---------------4
0
1
1
2
3
5
8
13
21
34
quit
---------------5
.
.
tick.
.
.
tick.
.
.
tick.
.
.
tick.
.
.
BOOM!
*/
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
2013年12月08日 wcdj
在go语言中,使用goroutine(a lightweight thread managed by the Go runtime)来实现并发程序。
go f(x, y, z)
starts a new goroutine running
f(x, y, z)
The evaluation of f, x, y, and z happens in the current goroutine and the execution off happens in the new goroutine.
Goroutines run in the same address space, so access to shared memory must be synchronized. Thesync package provides useful primitives, although you won't need them much
in Go as there are other primitives. (See the next slide, Channels.http://tour.golang.org/#64)
简单的测试用例:
package main
import (
"fmt"
"time"
)
func main() {
// A goroutine is a lightweight thread managed by the Go runtime
// Goroutines run in the same address space, so access to shared memory must be synchronized
go say("world")
say("hello")
fmt.Println("---------------1")
a := []int{7, 2, 8, -9, 4, 0}
// Channels are a typed conduit through which you can send and receive values with the channel operator, <-
// By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
fmt.Println("---------------2")
// Channels can be buffered. Provide the buffer length as the second argument to make to initialize a buffered channel
c2 := make(chan int, 2)
c2 <- 1
c2 <- 2
//c2 <- 3// error, the send buffer is full that will causes deadlock!
fmt.Println(<-c2)
fmt.Println(<-c2)
//fmt.Println(<-c2)// error, the receive buffer is empty that will causes deadlock too!
fmt.Println("---------------3")
c3 := make(chan int, 10)
go fibonacci(cap(c3), c3)
for i := range c3 {
fmt.Println(i)
}
fmt.Println("---------------4")
c4 := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c4)
}
quit <- 0
}()
fibonacci2(c4, quit)
fmt.Println("---------------5")
// The default case in a select is run if no other case is ready
// Use a default case to try a send or receive without blocking
tick := time.Tick(100 * time.Millisecond)
boom := time.After(500 * time.Millisecond)
for {
select {
case <-tick:
fmt.Println("tick. ")
case <-boom:
fmt.Println("BOOM!")
return
default:
fmt.Println(" .")
time.Sleep(50 * time.Millisecond)
}
}
}
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // send sum to c
}
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
// Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic
// Another note: Channels aren't like files; you don't usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop
close(c)
}
// The select statement lets a goroutine wait on multiple communication operations
// A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready
func fibonacci2(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
/*
output:
hello
world
hello
world
hello
world
hello
world
hello
---------------1
world
17 -5 12
---------------2
1
2
---------------3
0
1
1
2
3
5
8
13
21
34
---------------4
0
1
1
2
3
5
8
13
21
34
quit
---------------5
.
.
tick.
.
.
tick.
.
.
tick.
.
.
tick.
.
.
BOOM!
*/