引言
Golang(又称Go语言)因其并发编程的高效和简洁而受到广大开发者的喜爱。Go语言的并发模型基于goroutine和channel,这使得开发者可以轻松实现多线程的并行计算。本文将深入探讨Golang的并发编程,通过实战示例代码,帮助读者全面理解并发编程的原理和技巧。
并发编程基础
Goroutine
Goroutine是Go语言并发编程的核心,它是轻量级的线程,由Go运行时自动管理。每个goroutine都有自己的栈,但是共享同一份数据。
package main
import (
“fmt”
“sync”
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(“Hello from goroutine!”)
}()
wg.Wait()
}
在上面的代码中,我们创建了一个goroutine,它将输出“Hello from goroutine!”。
Channel
Channel是goroutine之间通信的桥梁,通过channel可以实现goroutine之间的同步和数据传递。
package main
import (
“fmt”
“time”
)
func worker(id int, c chan int) {
for n := range c {
fmt.Println(“Worker”, id, “received”, n)
}
}
func main() {
jobs := make(chan int, 5)
var wg sync.WaitGroup
for w := 1; w <= 3; w++ { wg.Add(1) go func(w int) { defer wg.Done() worker(w, jobs) }(w) } for j := 1; j <= 10; j++ { jobs <- j } close(jobs) wg.Wait() } 在这个例子中,我们创建了三个worker goroutines,它们从jobs channel中读取整数。main goroutine向jobs channel发送10个整数,然后关闭channel,并等待所有worker完成。 并发模式 WaitGroup sync.WaitGroup 是一个同步原语,用于等待一组goroutine完成。 package main import ( "fmt" "sync" "time" ) func worker(wg *sync.WaitGroup, id int) { defer wg.Done() fmt.Println("Worker", id, "is working") time.Sleep(time.Second) } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go worker(&wg, i) } wg.Wait() } 在上面的代码中,我们创建了5个goroutine,每个goroutine都会在main goroutine完成之前执行。 Mutex sync.Mutex 是一个互斥锁,用于保护共享资源。 package main import ( "fmt" "sync" ) var mu sync.Mutex var count = 0 func increment() { mu.Lock() count++ mu.Unlock() } func main() { for i := 0; i < 1000; i++ { go increment() } fmt.Println(count) } 在这个例子中,我们创建了1000个goroutine,每个goroutine都会调用increment函数来增加count的值。由于我们使用了互斥锁,所以最终count的值应该是1000。 总结 通过本文的实战示例代码,我们可以看到Golang并发编程的强大和简洁。掌握并发编程对于提高程序性能和可扩展性至关重要。希望本文能够帮助读者更好地理解和应用Golang的并发编程技术。