Threadsafe
是一个常出现在文档中的术语,但很少有人解释它的含义,特别是对于初学线程的人来说更难理解。
那么,如何向初学者解释 Threadsafe
代码呢?我目前的想法选项有:
- 列举使代码线程安全和线程不安全的因素清单
- 书本定义
- 一个有用的比喻
Threadsafe
是一个常出现在文档中的术语,但很少有人解释它的含义,特别是对于初学线程的人来说更难理解。
那么,如何向初学者解释 Threadsafe
代码呢?我目前的想法选项有:
当我被问到“这段代码是线程安全的吗?”时,我总是要反问:“你所关心的确切线程情况是什么?”和“在每种情况下对象的正确行为是什么?”。
无法简单地说代码是“线程安全的”,而不传达使用线程安全机制所防止和未防止的不良行为是没有帮助的。
我可能有所错误,但线程安全的一个标准是只使用局部变量。如果在不同的线程中调用同一函数时使用全局变量,结果将是不确定的。
线程安全的函数/对象(以下简称对象)是一种被设计用于支持多个并发调用的对象。这可以通过对并行请求进行序列化或某种交织调用的支持来实现。
如果该对象能够安全地支持并发请求(来自多个线程),则它是线程安全的。如果它不是线程安全的,则多个并发调用可能会破坏其状态。
考虑一个酒店的日志记录簿。如果一个人正在写入日志,另一个人同时开始写他的信息,最终结果将是两个信息的混合。这也可以通过多个线程写入输出流来演示。
线程安全的代码是指不会因为同一数据在两个地方同时被修改而导致失败的代码。线程安全是比并发安全更小的概念,因为它假定实际上是同一程序的两个线程进行了操作,而不是硬件修改数据或操作系统。
该术语特别有价值的一点是,它位于并发行为的光谱上,其中线程安全是最强的,中断安全比线程安全更弱,而可重入性则更弱。
在线程安全的情况下,这意味着所涉及的代码符合一致的API,并利用资源,以便其他代码在不同线程中(例如其自身的另一个并发实例)不会导致不一致性,只要它也符合相同的使用模式。对于任何合理的线程安全期望,必须指定使用模式。
中断安全约束通常不会出现在现代用户空间代码中,因为操作系统在隐藏此方面方面做得非常好,但在内核模式下这非常重要。这意味着即使在执行过程中触发了中断,代码也将成功完成。
最后一个,可重入性,在所有现代语言中都几乎可以保证,在用户空间内外都是如此,它只是意味着代码段可以被多次输入,即使在旧情况下执行尚未继续执行代码段。例如,在递归函数调用的情况下可能会发生这种情况。通过访问非可重入代码中的共享全局状态变量,很容易违反语言提供的可重入性。