golang Context for goroutines

Time:2020-10-31
  • outline
  • The control of goroutine
    • Cancel control
    • Timeout control
    • Value transfer between goroutines
  • summary

outline

The channel mechanism provided by golang is a concurrent mode based on CSP (communicating sequential processes) model

Through the channel, you can write more than oneSynergetic processIt is very simple to change the sequential code into parallel code. After transforming into parallel code, although it can make better use of multi-core hardware and effectively improve the code execution efficiency, it also brings the problem of code control

The parallel code is obviously more difficult to manage and control than the sequential code. In this case, we have to rely on the context interface provided by golang to help us control goroutine

The control of goroutine

The most basic control between goroutines is to exchange data through channels

1  func routineSample() {
 2    ch := make(chan int, 10)
 3    go p1(ch)
 4    go c1(ch)
 5    go c2(ch)
 6  
 7    time.Sleep(10 * time.Second)
 8  }
 9  
10  func p1(ch chan int) {
11    fmt.Println("Parent go routine!")
12  
13    for i := 0; i < 10; i++ {
14      ch

The above is the most basic example. The P1 function continuously sends data to the channel, and C1 and C2 are responsible for processing the data. Although it is very simple to realize the concurrency of C1 and C2 through the channel, we can see that it is not so easy for P1 to control C1 and C2

In this case, it is necessary to control the concurrent coroutine through the context interface

Cancel control

Canceling control means that the initiator of a task sends a signal indicating that the task has been received by the initiator to stop the execution of the task

1  func routineSample() {
 2   ch := make(chan int, 10)
 3   ctx, cancel := context.WithCancel(context.Background())
 4   go p1(ctx, ch)
 5   go c1(ctx, ch)
 6   go c2(ctx, ch)
 7  
 8 // cancel the task after 300 ms
 9   time.Sleep(300 * time.Millisecond)
10   cancel()
11  
12   time.Sleep(10 * time.Second)
13  }
14  
15  func p1(ctx context.Context, ch chan int) {
16   fmt.Println("Parent go routine!")
17  
18   for i := 0; i < 10; i++ {
19     ch

After 300 ms, the signal to cancel the task is sentcancel()C 1 and C 2 judge whether there is a cancellation signal by select, and exit the processing after receiving the cancellation signal

It can be seen from the execution results that C1 and C2 stop exiting after processing about 5 ~ 6 tasks

Timeout control

In addition to canceling control, context also has time-out control

1  func routineSample() {
 2   ch := make(chan int, 10)
 3   ctx, _ := context.WithTimeout(context.Background(), 300*time.Millisecond)
 4   go p1(ctx, ch)
 5   go c1(ctx, ch)
 6   go c2(ctx, ch)
 7  
 8   time.Sleep(10 * time.Second)
 9  }
10  
11  func p1(ctx context.Context, ch chan int) {
12   fmt.Println("Parent go routine!")
13  
14   for i := 0; i < 10; i++ {
15     ch

Control timeoutWithTimeoutAlso return onecancelFunction can be used to cancel the execution of a task before the timeout arrives. In the above example, the task is automatically cancelled after the timeout period is reachedcancelFunction

Value transfer between goroutines

Generally speaking, the transmission between goroutines is business data through channel. In addition, some metadata controlling goroutine can also be transferred through channel

1  func routineSample() {
 2   ch := make(chan int, 10)
 3 // when goroutine receives task 5, it quits and does no more follow-up tasks
 4   ctx := context.WithValue(context.Background(), "finish", 5)
 5   go p1(ctx, ch)
 6   go c1(ctx, ch)
 7   go c2(ctx, ch)
 8  
 9   time.Sleep(10 * time.Second)
10  }
11  
12  func p1(ctx context.Context, ch chan int) {
13   fmt.Println("Parent go routine!")
14  
15   for i := 0; i < 10; i++ {
16     ch

In the above example, a task number with key = finish is placed in the context. If C1 or C2 receives the same task number as it, it will exit the execution of the task. From running the above example, it can be seen that when C1 or C2 executes task No. 5, it will exit the program. However, it is uncertain who receives task No. 5. Execute the above code several times, It can be found that sometimes C1 exits, sometimes C2 exits

summary

Context is the context for controlling concurrent coroutines. By using context, you can greatly simplify the code for controlling the timeout of coroutines, canceling the execution of coroutines, and transferring values between coroutines. Context is very convenient, but it can’t be misused. The business data transmitted through channel should not be passed in context

In addition, context is thread safe and can be safely used in multiple coroutines