Concurrency Go
Concurrency Go
Được dịch sang: Anh Hiển thị văn bản gốc Tùy chọn ▼
concurrency
goroutine
Goroutines are at the heart of Go's parallel design. After all, goroutine is actually a coroutine, but it is
smaller than an execution thread. A dozen goroutines may be reflected in five or six execution threads at
the bottom layer. The Go language helps you realize memory sharing between these goroutines.
Execution of goroutine requires very little stack memory (about 4~5KB), and of course it will scale
according to the corresponding data. Because of this, thousands of concurrent tasks can be executed at
the same time. Goroutine is easier to use, more efficient, and lighter than thread.
Goroutine is a thread manager managed by Go's runtime. Goroutine is implemented through the go
keyword, which is actually an ordinary function.
go hello(a, b, c)
package main
import (
"fmt"
"runtime"
runtime.Gosched()
fmt.Println(s)
func main() {
go say("world") //開一個新的Goroutines執行
say("hello") //當前Goroutines執行
// 以上程式執行後將輸出:
// hello
// world
// h ll
https://md2pdf.netlify.app 1/6
12/2/22, 9:42 AM concurrency
// hello
// world
Được dịch sang: Anh Hiển thị văn bản gốc Tùy chọn ▼
// hello
// world
// hello
// world
// hello
The above multiple goroutines execute in the same program and share memory data, but we must
follow the design: do not communicate through sharing, but share through communication.
channels
Goroutines execute in the same address space, so access to shared memory must be synchronized. So
how to communicate data between goroutines? Go provides a good communication mechanism
channel. A channel can be compared to a two-way pipe in a Unix shell: values can be sent or received
through it. These values can only be of a specific type: channel type. When defining a channel, you also
need to define the type of the value passed to the channel. Note that the channel must be created with
make:
ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{})
The channel receives and sends data through the operator <-
v := <-ch // 從ch中接收資料,並賦值給v
example:
package main
import "fmt"
total := 0
for _, v := range a {
total += v
https://md2pdf.netlify.app 2/6
12/2/22, 9:42 AM concurrency
}
Được dịch sang: Anh Hiển thị văn bản gốc Tùy chọn ▼
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
fmt.Println(x, y, x + y)
By default, channels block receiving and transmitting data unless the other end is ready, which makes it
easier to synchronize Goroutines without requiring explicit locks. The so-called blocking means that if
you read (value := <-ch), it will be blocked until there is data received. Second, any transfer (ch<-5) will
be blocked until the data is read. Unbuffered channels are a great tool for synchronizing between
multiple goroutines.
Buffered Channels
In addition to the default non-cache type channels above, Go also allows you to specify the buffer size of
the channel, which is very simple, that is, how many elements the channel can store. ch:= make(chan
bool, 4), create a bool channel that can store 4 elements. In this channel, the first 4 elements can be
written without blocking. When writing the 5th element, the code will block until some other goroutine
reads some elements from the channel to make room.
When value = 0, the channel is unbuffered and blocked for reading and writing. When value > 0, the
channel is buffered and non-blocking, and writing is blocked until value elements are filled. example:
package main
import "fmt"
func main() {
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
//修改為1報如下的錯誤:
https://md2pdf.netlify.app 3/6
12/2/22, 9:42 AM concurrency
//修改為1報如下的錯誤:
//fatal error:Được
all dịch
goroutines
sang: Anhare asleep
Hiển thị- văn
deadlock!
package main
import (
"fmt"
x, y := 1, 1
c <- x
x, y = y, x + y
close(c)
func main() {
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
for i := range c can continuously read the data in the channel until the channel is explicitly closed. In the
above code, we can see that the channel can be closed explicitly, and the producer closes the channel
through the built-in function close. After the channel is closed, no more data can be sent. The consumer
can use the syntax v, ok := <-ch to test whether the channel is closed. If ok returns false, then the
channel has no data and has been closed.
Select
The above descriptions are all about the case of only one channel, so how do we operate if there are
multiple channels? Go provides a keyword select, through which the data flow on the channel can be
monitored.
https://md2pdf.netlify.app 4/6
12/2/22, 9:42 AM concurrency
Được dịch sang: Anh Hiển thị văn bản gốc Tùy chọn ▼
The select default is blocking, and it will only be executed when there is transmission or reception in the
monitored channel. When multiple channels are ready, select is randomly selected for execution.
package main
import "fmt"
x, y := 1, 1
for {
select {
case c <- x:
x, y = y, x + y
case <-quit:
fmt.Println("quit")
return
func main() {
c := make(chan int)
go func() {
fmt.Println(<-c)
quit <- 0
}()
fibonacci(c, quit)
There is also default syntax in select, select is actually a function similar to switch, and default is executed
by default when none of the monitored channels is ready (select will no longer block waiting for the
channel).
select {
case i := <-c:
// use i
default:
// 當c阻塞的時候執行這裡
time out
https://md2pdf.netlify.app 5/6
12/2/22, 9:42 AM concurrency
time out
Được dịch sang: Anh Hiển thị văn bản gốc Tùy chọn ▼
Sometimes goroutines will be blocked, so how can we avoid the entire program from being blocked? We
can use select to set the timeout, as follows:
func main() {
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <- c:
println(v)
println("timeout")
o <- true
break
}()
<- o
runtime goroutine
There are several functions in the runtime suite that handle goroutines:
1. Goexit exits the currently executing goroutine, but the defer function will continue to call
2. Gosched gives up the execution permission of the current goroutine, the scheduler schedules other
waiting tasks to execute, and resumes execution from that location sometime next time.
5. GOMAXPROCS is used to set the maximum number of CPU cores that can be calculated in parallel,
and returns the previous value.
Summarize
At present, several servers only use the function of channels, and I still make a file for your reference, so
that those who have never operated or newcomers can understand this function.
https://md2pdf.netlify.app 6/6