Home >Backend Development >Golang >Efficient concurrent programming: using Go WaitGroup and coroutine pools
Efficient concurrent programming: using Go WaitGroup and coroutine pool
Introduction:
In modern computer systems, concurrent programming is becoming more and more important. Concurrent programming can maximize the use of multi-core processor performance and improve program execution efficiency. However, concurrent programming also faces challenges, such as dealing with synchronization and management of concurrent tasks. In this article, we will introduce how to use WaitGroup and coroutine pool in Go language to achieve efficient concurrent programming, and provide specific code examples.
1. Use of WaitGroup:
Go language provides a very useful WaitGroup type, which can be used to wait for a group of coroutines to complete execution. The following is a simple example that shows how to use WaitGroup to achieve synchronization of concurrent tasks:
package main import ( "fmt" "sync" ) func worker(id int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("Worker %d starting ", id) // 模拟耗时的任务 for i := 0; i < 5; i++ { fmt.Printf("Worker %d: %d ", id, i) } fmt.Printf("Worker %d done ", id) } func main() { var wg sync.WaitGroup // 启动5个协程 for i := 0; i < 5; i++ { wg.Add(1) go worker(i, &wg) } // 等待所有协程执行完毕 wg.Wait() }
In the above code, we define a worker function to simulate time-consuming tasks. We notify the WaitGroup that the task has been completed by passing in a pointer to the WaitGroup. In the main function, we started 5 coroutines and notified WaitGroup to increase the number of waiting tasks by calling the wg.Add(1)
method. Finally, we call the wg.Wait()
method to block the main coroutine until all tasks are completed.
2. Use of coroutine pool:
Go language also provides the implementation of coroutine pool, which is used to limit the number of concurrency and prevent too many coroutines from running at the same time. The coroutine pool can help us balance system resources and avoid resource waste. Here is an example that shows how to use a coroutine pool to perform tasks:
package main import ( "fmt" "sync" ) type Pool struct { workers chan struct{} wg sync.WaitGroup } func NewPool(size int) *Pool { return &Pool{ workers: make(chan struct{}, size), } } func (p *Pool) AddTask(task func()) { p.workers <- struct{}{} p.wg.Add(1) go func() { task() <-p.workers p.wg.Done() }() } func (p *Pool) Wait() { p.wg.Wait() } func main() { pool := NewPool(3) // 添加10个任务到协程池 for i := 0; i < 10; i++ { taskID := i pool.AddTask(func() { fmt.Printf("Task %d is running ", taskID) }) } // 等待所有任务完成 pool.Wait() }
In the above code, we define a Pool structure that contains a workers channel for limiting the number of coroutines and a WaitGroup is used to wait for all tasks to complete. We write an empty structure into the channel by calling p.workers <- struct{}{}
, indicating that a coroutine is executing the task; by calling <-p.workers
Take out an empty structure from the channel, indicating that a coroutine has completed its task. In the AddTask method, we add the task to the coroutine pool and take out an empty structure from the channel after the task execution is completed. Finally, call the pool.Wait()
method to wait for all tasks to complete.
Conclusion:
By using WaitGroup and coroutine pool, we can easily achieve efficient concurrent programming. WaitGroup helps us synchronize the execution of concurrent tasks, while the coroutine pool limits the number of concurrencies and improves the utilization of system resources. In actual applications, we can adjust the size of the coroutine pool according to needs to make full use of the computer's performance.
The above is the detailed content of Efficient concurrent programming: using Go WaitGroup and coroutine pools. For more information, please follow other related articles on the PHP Chinese website!