返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

9.1.3 调度

发布于 2024-10-12 19:15:49 字数 1645 浏览 0 评论 0 收藏 0

除运行时自动调度外,某些时候需要手动控制任务执行。

挂起

暂时挂起任务,释放线程去执行其他任务。
当前任务被放回任务队列,等待下次被某个线程重新获取后继续执行。

也就是说,一个任务不一定由同一线程完成。实际上,除了主动协作调度外,还要考虑运行时抢占调度等因素。长时间运行的任务会被暂停,让其他等待任务有机会执行,以确保公平。

package main

import (
	"sync"
	"runtime"
)

func main() {
    
    // 限制并发任务数。
	runtime.GOMAXPROCS(1)

	var wg sync.WaitGroup
	wg.Add(2)

	a, b := make(chan struct{}), make(chan struct{})

	go func() {
		defer wg.Done()

		<- a
		for i := 0; i < 5; i++ {
			println("a", i)
		}
	}()

	go func() {
		defer wg.Done()

		<- b
		for i := 0; i < 5; i++ {
			println("b", i)
			if i == 2 { runtime.Gosched() }
		}
	}()

    // 安排执行次序。
    close(b)
    close(a)
    
	wg.Wait()
}

/* --- output -----------
b 0
b 1
b 2  <---- PAUSE
a 0
a 1
a 2
a 3
a 4
b 3  <---- CONT
b 4
*/

发令

暂停一批任务,直到某个信号发出。

func main() {
	var wg sync.WaitGroup
	r := make(chan struct{})
    
	for i := 0; i < 10; i++ {
		wg.Add(1)

		go func(id int){
			defer wg.Done()

			<- r            // 阻塞,等待信号。
			println(id)
		}(i)
	}
    
    close(r)
	wg.Wait()
}

也可反向使用 sync.WaitGroup ,让多个 goroutine Wait ,然后 main Done
类似实现,还有信号量,可以控制启动任务数量。

次序

多个任务按特定次序执行。

func main() {
	const CNT = 5

    var wg sync.WaitGroup
	wg.Add(CNT)

	var chans [CNT]chan struct{}
    
	for i := 0; i < CNT; i++ {
		chans[i] = make(chan struct{})

		go func(id int){
			defer wg.Done()
			<- chans[id]
			println(id)
		}(i)
	}

	// 次序(延时,给调度器时间处理)
	for _, x := range []int{4, 0, 1, 3, 2} {
		close(chans[x])
		time.Sleep(time.Millisecond * 10)
	}

	wg.Wait()
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文