Home >Backend Development >Golang >Let's talk about some commonly used Golang concurrent programming techniques
Golang is a programming language widely used to build efficient, high-performance, parallel and distributed programs. It has the advantage of a simple, lightweight syntax while being able to easily use concurrent programming.
In Golang, using goroutine and channel to implement concurrent programming is a popular way. Goroutine is a lightweight thread unique to Golang. It can execute multiple tasks at the same time in a single thread, and can switch with zero overhead when the tasks are not blocked. Channel is a synchronization primitive that allows multiple goroutines to collaborate to complete data transfer and synchronization between tasks.
Let’s take a look at some common Golang concurrent programming skills:
1. Use goroutine to achieve concurrency
Goroutine in Golang is very easy to use, you only need to use goroutine before calling the function Adding a "go" keyword turns it into a goroutine. For example:
func main() { //启动一个新的goroutine go func() { fmt.Println("Hello World") }() //在这里继续执行其他任务 //... }
The above code will print "Hello World" in another thread, and the main function will continue to execute at the same time. Using goroutine can greatly improve the concurrency and response speed of the program.
2. Use channel to achieve data synchronization
Golang's channel is a synchronization primitive used to transfer data and synchronize between multiple goroutines. Channel can establish communication between any two goroutines. It has two ways of sending and receiving messages, blocking and non-blocking.
The following is a simple example using channel to transfer data:
func main() { //创建一个整数类型的channel ch := make(chan int) //启动一个goroutine发送数据 go func() { ch <- 123 //发送数据到channel中 }() //接收刚刚发送的数据 num := <- ch //从channel中接收数据 fmt.Println(num) //输出:123 }
In the above code, we first create a channel of integer type. Then a goroutine is started to send data to it, and then the data is received from the channel in the main thread and output. Channels can be used to transfer and synchronize data between different goroutines.
3. Use sync package to achieve synchronization
sync is a collection of synchronization primitives in Golang, including Mutex, RWMutex, Cond, Once, WaitGroup, etc. Can be used to implement higher-level synchronization and thread-safety control.
Mutex is a mutex lock used to protect shared resources. Use the Lock() function to obtain the mutex before accessing the critical section, and use the Unlock() function to release the lock after the access is completed.
The following is an example of a thread-safe counter implemented using Mutex:
import ( "fmt" "sync" ) type Counter struct { count int mu sync.Mutex } func (c *Counter) Increment() { //获取互斥锁并增加计数 c.mu.Lock() c.count++ c.mu.Unlock() } func (c *Counter) Count() int { //获取互斥锁并返回计数 c.mu.Lock() defer c.mu.Unlock() return c.count } func main() { //创建一个计数器 c := Counter{} //启动多个goroutine增加计数 for i := 0; i < 1000; i++ { go c.Increment() } //等待所有goroutine执行完成 time.Sleep(time.Second) //输出计数器的值 fmt.Println(c.Count()) }
In the above code, we use Mutex to protect the counter shared resource and ensure that it is safe when multiple goroutines are executed concurrently. Thread safety.
4. Use the context package to implement timeout control
In Golang, context is a transitive context used to control the behavior of the goroutine subtree (similar to ThreadLocal in Java).
The context package provides some functions, such as WithCancel(), WithDeadline(), WithTimeout(), etc., which can be used to start goroutine context management. These functions return a new context object and a function that can be called to mark the context as canceled when the context needs to be cancelled. In goroutine, you can use the Done() channel of Context to obtain the cancellation signal.
The following is an example of timeout control implemented using context:
import ( "fmt" "context" ) func main() { //创建一个带超时的上下文 ctx, cancel := context.WithTimeout(context.Background(), time.Second) //执行一个耗时任务 go func() { time.Sleep(time.Second * 2) fmt.Println("Goroutine Done") }() //等待上下文取消信号 select { case <-ctx.Done(): fmt.Println("Timeout") } //取消上下文 cancel() }
In the above code, we first created a context with a timeout of 1 second and started a context that took 2 seconds. goroutine, and then wait for the Done() channel of the context in the main function. Once the cancellation signal is received, "Timeout" will be output.
5. Use sync/atomic to implement atomic operations during competition
In Golang, the sync/atomic package provides some atomic operation functions that can be used to update shared integers during competition. or pointer value. Using atomic operations can avoid race conditions when multiple goroutines execute concurrently.
The following is an example of an atomic operation using the sync/atomic package to output a hexadecimal counter:
import ( "fmt" "sync/atomic" ) func main() { //定义一个uint32的计数器 var counter uint32 //启动多个goroutine更新计数器 for i := 0; i < 1000; i++ { go func() { //原子地增加计数器 atomic.AddUint32(&counter, 1) }() } //等待所有goroutine执行完成 time.Sleep(time.Second) //输出计数器的值 fmt.Printf("0x%x\n", atomic.LoadUint32(&counter)) }
In the above code, we define a uint32 type counter and use The AddUint32() function atomically increments the count when multiple goroutines execute concurrently. Finally, the hexadecimal value of the counter is output.
Summary:
Concurrent programming in Golang has the characteristics of simplicity, lightweight, and high performance. Through the use of tool functions such as goroutine, channel, and sync, collaboration between threads can be easily realized. and communication to improve the concurrency performance and response speed of the program. At the same time, attention needs to be paid to the use of synchronization mechanisms to avoid thread safety issues.
The above is the detailed content of Let's talk about some commonly used Golang concurrent programming techniques. For more information, please follow other related articles on the PHP Chinese website!