golang select语句是如何实现的
How are golang select statements implemented?
特别是,我在C++中有一些阻塞队列,我想等到其中任何一个有我可以弹出的项目。
我能想到的唯一机制是为每个从输入队列弹出的队列生成一个单独的线程,并将其馈送到原始线程可以等待的主队列中
每次我想从一组队列中弹出时,都要生成N个新线程,然后将它们全部杀死,这似乎有点耗费资源。
Golang是否实现了一些更优雅的机制,我可以在自己的C++代码中实现这些机制?
我不一定说Go的select
实现很优雅,但我认为它以自己的方式很漂亮,而且经过了相当优化。
- 它通过一个非默认情况特殊处理
select
- 它改变了评估案例的顺序,以避免确定性饥饿
- 它乐观地第一次通过案例,寻找一个已经满意的案例
- 它使用许多只为运行时机制所知的内部机制,在每个通道的内部发送方/接收方队列中排队
- 它使用类似轻量级goroutine引用的
sudog
(同一个goroutine可能有许多sudog
),允许快速跳转到goroutine堆栈 - 它使用调度器的
gopark
机制来阻止自己,这允许对信号进行有效的解封 - 当发出信号并取消标记时,它会通过操作
select
goroutine的程序计数器立即进入触发的事例处理程序函数
- 它使用类似轻量级goroutine引用的
在实施过程中没有一个总体的突破性想法,但你会非常感激如何仔细地修改每一步,使其快速、高效,并与渠道的概念很好地结合在一起。正因为如此,用另一种语言重新实现Go的select
语句并不容易,除非您至少首先拥有chan
构造。
你可以看看其他语言中的重新实现,在这些语言中,这个想法以不同程度的相似性和有效性进行了重新实现。如果我必须用另一种语言从头开始重新实现select
,我可能会首先尝试一个共享信号量,如果它不起作用,则切换到一个更粗糙的、睡眠不足的随机检查策略。
Golang的select
语句的灵感来自C select
函数(请参阅GNU libc文档),该函数用于等待一组文件描述符上的I/O。如果您的队列使用套接字或管道进行通信,则可以使用它。
相关文章:
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如何实现内部实现依赖于模板参数的类
- 我的 PRNG 实现与我尝试复制的实现有何不同?