下面是一个使用 Go 编写的示例程序,实现了主协程不断添加任务,子协程消费任务并将结果记录到主协程的变量中,并且确保了多个协程之间的访问安全。
package main
import (
"fmt"
"sync"
)
type Job struct {
ID int
Result int
}
func worker(id int, jobs <-chan Job, results chan<- Job) {
for job := range jobs {
job.Result = job.ID * 2 // 示例中的工作是将 ID 值乘以 2
results <- job
}
}
func main() {
jobs := make(chan Job)
results := make(chan Job)
done := make(chan struct{})
var wg sync.WaitGroup
// 启动五个子协程
for i := 1; i <= 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
worker(id, jobs, results)
}(i)
}
go func() {
wg.Wait()
close(results) // 所有子协程退出后关闭结果通道
}()
go func() {
for result := range results {
fmt.Printf("Job ID: %d, Result: %d\n", result.ID, result.Result)
}
done <- struct{}{}
}()
for i := 1; i <= 10; i++ { // 主协程添加10个任务
jobs <- Job{ID: i}
}
close(jobs) // 所有任务添加完成后关闭任务通道
<-done // 等待输出结果完成
fmt.Println("All jobs have been completed.")
}
上述代码中,通过创建一个任务通道 jobs
和结果通道 results
,主协程不断向任务通道发送任务。子协程从任务通道接收任务并处理,并将结果发送到结果通道。主协程在另外一个 goroutine 中从结果通道接收结果并输出。
通过使用 sync.WaitGroup
来等待所有子协程完成工作,并使用信号量 done
来确保输出结果完成后程序才退出。这样可以保证多个协程之间的安全访问和正确的执行顺序。
请注意,上述示例只是一个简单的演示,实际情况可能需要根据具体需求进行适当调整和扩展。
内容由零声教学AI助手提供,问题来源于学员提问