方式1
package main
import (
"fmt"
"sync"
"time"
)
func doWork(id int, resultChan chan<- int, wg *sync.WaitGroup) {
defer wg.Done() // 表示goroutine完成
time.Sleep(time.Duration(id) * time.Second) // 模拟工作负载
resultChan <- id * 2 // 发送结果到channel
}
func main() {
var wg sync.WaitGroup
resultChan := make(chan int, 5) // 假设我们有5个goroutine
// 启动多个goroutine
for i := 1; i <= 5; i++ {
wg.Add(1) // 增加WaitGroup计数
go doWork(i, resultChan, &wg)
}
// 等待所有goroutine完成
go func() {
wg.Wait() // 等待所有goroutine完成
close(resultChan) // 完成所有工作后关闭channel
}()
// 收集所有结果
for result := range resultChan {
fmt.Println("Result:", result)
}
}
方式2
package main
import (
"fmt"
"time"
)
func doWork(id int, resultChan chan<- int, doneChan chan<- struct{}) {
time.Sleep(time.Duration(id) * time.Second) // 模拟工作负载
resultChan <- id * 2 // 发送结果到channel
doneChan <- struct{}{} // 发送信号表示完成
}
func main() {
resultChan := make(chan int, 5) // 存储结果
doneChan := make(chan struct{}, 5) // 信号channel,表示5个goroutine完成
for i := 1; i <= 5; i++ {
go doWork(i, resultChan, doneChan)
}
// 收集所有结果
for i := 1; i <= 5; i++ {
result := <-resultChan
fmt.Println("Result:", result)
<-doneChan // 等待一个goroutine完成
}
close(resultChan) // 完成后关闭channel
}
方式3 推荐
package main
import (
"fmt"
"sync"
)
// calculateSum 计算从start到end(含)的整数和
func calculateSum(start, end int) int {
sum := 0
for i := start; i <= end; i++ {
sum += i
}
return sum
}
func main() {
var mu sync.Mutex // 互斥锁,用于保护共享变量
var cond = sync.Cond{L: &mu} // 条件变量,初始化时传入互斥锁
numGoroutine := 5 // 并发执行的goroutine数量
partialSums := make([]int, numGoroutine) // 存储每个goroutine计算的部分和
completed := 0 // 完成的goroutine计数
// 计算每个goroutine负责的范围
chunkSize := 10000 / numGoroutine
// 启动numGoroutine个goroutine执行任务
for i := 0; i < numGoroutine; i++ {
go func(id int) {
start := id*chunkSize + 1
end := (id + 1) * chunkSize
// 处理边界情况,确保最后一个goroutine包含10000
if id == numGoroutine-1 {
end = 10000
}
partialSum := calculateSum(start, end)
mu.Lock()
partialSums[id] = partialSum
completed++
if completed == numGoroutine {
cond.Broadcast() // 如果所有任务都完成了,广播通知
}
mu.Unlock()
}(i)
}
// 等待所有任务完成
mu.Lock()
for completed < numGoroutine {
cond.Wait() // 等待条件变量通知
}
mu.Unlock()
// 计算总和
totalSum := 0
for _, partialSum := range partialSums {
totalSum += partialSum
}
// 打印总和
fmt.Println("Total sum:", totalSum)
}