看完检查并设置后的维基百科条目 ,我还是留下一个问题:“什么会测试和设置可以用来做什么?”
我知道,你可以用它来实现互斥(如在维基百科中描述),但它有什么其他用途?
看完检查并设置后的维基百科条目 ,我还是留下一个问题:“什么会测试和设置可以用来做什么?”
我知道,你可以用它来实现互斥(如在维基百科中描述),但它有什么其他用途?
您可以使用它,你想要做一些工作之后将数据写入内存,并确保另一个线程不覆盖目标,因为你随时开始。 很多锁/无互斥算法,采取这种形式。
一个很好的例子是“增量”。
说两个线程执行a = a + 1
。 说a
与价值开始100
。 如果两个线程都在同一时间(多芯)上运行,既将加载a
如100
,递增到101
,和存储,早在a
。 错误!
随着检查并设置,你说的“设置a
到101
,但只有当它目前拥有价值100
”。 在这种情况下,一个线程将通过这个测试,但对方会失败。 在故障情况下,线程可以重试整个语句,这一次装入a
为101
。 成功。
这通常比使用互斥,因为速度快:
想象一下你正在编写一个银行应用程序,而应用程序不得不退出十磅的请求(是的,我的英语;)从账户)。 所以,你需要读取当前账户余额到一个局部变量,减去提款,然后写平衡回内存。
但是,如果另一个并发请求你们之间发生读取值,你写出来? 还有那该请求的结果将被首先得到完全覆盖的可能性,以及账户余额将不正确。
检查并设置帮助我们通过检查你的价值覆盖是什么,你认为它应该是解决这个问题。 在这种情况下,您可以检查余额为您阅读原始值。 由于它的原子,它的不可中断所以没有人可以从下你拉地毯出读取和写入之间。
解决同样的问题,另一种方法是取出的存储位置的锁。 不幸的是,锁是极其难以得到的权利,难推理,具有可扩展性问题,并在失败面前表现不好,所以他们不是一个理想的(但绝对实用)的解决方案。 检查并设置方法形成一些软件事务记忆的基础上,其乐观让每一笔交易同时执行,在滚动他们都回来了,如果他们发生冲突的成本。
基本上,它的使用是完全互斥,因为原子的巨大重要性。 而已。
检查并设置为可以与其他两个指令,非原子和更快(在多处理器系统,当原子负有硬件开销)执行的操作,所以一般你不会使用它的其他原因。
当你需要得到一个共同的价值,用它做什么,并更改该值它的使用,假设另一个线程尚未改变了它。
至于实际应用,最后一次见到它是在并发队列(队列可以推/多线程弹出,而无需信号灯或互斥)的实现。
为什么要使用检查并设置而非互斥? 因为它通常需要比互斥的开销更少。 其中一个互斥需要OS介入,一检查并设置可被实现为在CPU上的单一原子指令。 当与线程100的并行环境中运行,在代码关键部分的单一互斥体可能会导致严重的瓶颈。