关于select的选择执行的问题

来源:11-4 用select进行调度

weibo_隱懓_0

2018-02-25

select 我的理解是看下面的哪个channel有数据进来了,谁先有数据就先调度谁

不知道我理解的对不。

但是这样就有个疑问了,老师在讲select的时候

select {
		case n := <-c1:
			values = append(values, n)
		case n := <-c2:
			values = append(values, n)
		case activeWorker <- activeValue:
			values = values[1:]

		case <-time.After(800 * time.Millisecond):
			fmt.Println("timeout")
		case <-tick:
			fmt.Println(
				"queue len =", len(values))
		case <-tm:
			fmt.Println("bye")
			return
		}

里面的time.After,tick,tm(timeout). 理论上是不是并不能保证实时执行?最终结果得看是否被调度到。

如果其他的channel的入通道的速度快于计时,那不就是并不能保证准时进行调度timeout或者其他计时channel了吗?

那么如何保证呢?

我想到的是把获取channel和计时相关的分开,用两个select进行调用,这样能保证计时准确实时生效了吧:

for {
    select {
        case n := <-c1:
		values = append(values, n)
	case n := <-c2:
		values = append(values, n)
	case activeWorker <- activeValue:
		values = values[1:]
    }
    select {
        case <-time.After(800 * time.Millisecond):
		fmt.Println("timeout")
	case <-tick:
		fmt.Println(
		"queue len =", len(values))
	case <-tm:
		fmt.Println("bye")
		return
    }
}

请问这样理解对吗?

写回答

1回答

ccmouse

2018-02-26

select的时候的确谁先有数据就调度谁,一起来数据的话调度器会随机兼顾公平。这个例子里,比如tm有了数据,但是选择了其它分支,那tm里的之前数据仍然在,等下一次select很可能就选择了tm。当然我们所要做的是在select的分支里不要花太多时间。

当然这的确不是实时和准确的。通用编程语言其实无法做到准确和实时。

比如你的修改里面,上面第一个select干活部分如果多花了点时间,那下面就不准确了。即使通过某种方法为这个时间的操作独占一个线程,仍然会遇到操作系统的调度问题。

不过你的修改不错的确对实时性有一定改善。有一个小问题,在第二个select里面可以加入default分支。那样如果三个时间有关的channel都没有数据的话,它不会卡在这里而是直接去下一个for干活。

0
5
weibo_隱懓_0
回复
ccmouse
老师 你上面回答的一句话,“即使通过某种方法为这个时间的操作独占一个线程,仍然会遇到操作系统的调度问题。” 就是说即使我为下面的select 单独开一个goroutine依然不能保证时效性对吗,这个地方不太明白,能再说说吗。
2018-02-26
共5条回复

Google资深工程师深度讲解Go语言 由浅入深掌握Go语言

语法+分布式爬虫实战 为转型工程师量身打造

5995 学习 · 1909 问题

查看课程