在Go语言中,例程(goroutine)和通道(channel)是实现并发编程的重要工具。通道提供了一种在多个例程之间安全传递数据的方式,而同步问题则是在并发编程中常见的挑战之一。
例程(Goroutine):
go
关键字启动。通道(Channel):
同步问题:
问题:数据竞争(Data Race)
问题:死锁(Deadlock)
使用通道来传递数据,而不是直接访问共享内存。
package main
import (
"fmt"
"sync"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("Worker %d started job %d\n", id, j)
results <- j * 2
fmt.Printf("Worker %d finished job %d\n", id, j)
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
var wg sync.WaitGroup
for w := 1; w <= 3; w++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
worker(id, jobs, results)
}(w)
}
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
go func() {
wg.Wait()
close(results)
}()
for r := range results {
fmt.Println("Result:", r)
}
}
确保通道的使用方式不会导致所有例程都在等待对方。
package main
import (
"fmt"
"time"
)
func deadlockExample() {
ch := make(chan int)
ch <- 1 // 这里会阻塞,因为没有接收者
fmt.Println(<-ch)
}
func noDeadlockExample() {
ch := make(chan int)
go func() {
ch <- 1 // 这里不会阻塞,因为有另一个例程在接收
}()
fmt.Println(<-ch)
}
func main() {
// deadlockExample() // 这会导致死锁
noDeadlockExample()
time.Sleep(time.Second)
}
通过合理设计通道的使用,可以有效避免并发编程中的同步问题。
领取专属 10元无门槛券
手把手带您无忧上云