9.4 并发
尽管做出了英勇的努力,并正在形成广泛的共识,但是人们所期望的通用并发模型(执行器
)在 C++20 中还没有准备好(§8.8.1)。这并非是因为缺乏努力,我们的努力中包括了 2018 年 9 月在华盛顿州贝尔维尔举行的为期两天的特别会议,约有 25 人出席,其中有来自英伟达、Facebook 和美国国家实验室的代表。不过,有几个不那么剧烈的有用改进还是及时完成了,其中包括:
jthread
和停止令牌 [Josuttis et al. 2019a]atomic<shared_ptr<T>>
[Sutter 2017b]- 经典的信号量 [Lelbach et al. 2019]
- 屏障和锁存器 [Lelbach et al. 2019]
- 小的内存模型的修复和改进 [Meredith and Sutter 2017]
jthread
(joining thread
的缩写)是一个遵守 RAII 的线程;也就是说,如果 jthread
超出作用域了,它的析构函数将汇合线程而不是终止程序:
void some_fct()
{
thread t1;
jthread t2;
// ...
}
在作用域的最后,t1
的析构函数会终止程序,除非 t1
的任务已经完成,已经 join
或 detach
,而 t2
的析构函数将会等待其任务完成。
一开始的时候(C++11 之前),很多人(包括我在内)都希望 thread
可以拥有如今 jthread
的行为,但是根植于传统操作系统线程的人坚持认为终止一个程序要远比造成死锁好得多。2012 年和 2013 年,Herb Sutter 曾经提出过汇合线程(joining thread)[Sutter 2012, 2013a]。这引发了一系列讨论,但最终却没有作出任何决定。2016 年,Ville Voutilainen 总结了这些问题,并为将汇合线程纳入 C++17 发起了投票 [Voutilainen 2016a]。投票支持者众多以至于我(只是半开玩笑地)建议我们甚至可以把汇合线程作为一个错误修复提交给 C++14。但是不知何故,进展又再次停滞。到了 2017 年,Nico Josuttis 又一次提出了这个问题。最终,在八次修订和加入了停止令牌之后,这个提案才成功进入了 C++20 [Josuttis et al. 2019a]。
停止令牌
解决了一个老问题,即如何在我们对线程的结果不再感兴趣后停止它。基本思想是使用协作式的线程取消方式(§4.1.2)。假如我想要一个 jthread
停止,我就设置它的停止令牌。线程有义务不时地去检查停止令牌是否被设置了,如果被设置了就进行清理和退出。这个技巧由来已久,几乎对于每一个有主循环的线程都能完好高效地工作,在这个主循环里就可以对停止令牌进行检查。
像往常一样,命名成了问题:safe_thread
、ithread
(i
代表可中断)、raii_thread
、joining_thread
,最终成了 jthread
。C++ 核心指南支持库 (GSL) 中称其为 gsl::thread
。说真的,最合适的名字就是 thread
,但是很不幸,那个名字已经被一类不太有用的线程占用了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论