对于高性能多线程系统,是否有确定性的方法/方法来确定使用仅比较和交换又称原子操作可以完成哪些并发逻辑,必须使用锁,半音和/或障碍?
我的系统总是涉及很多并发和多线程问题。有些很简单,因为如果需要快速简单的锁定就可以解决问题。但对于一些复杂的问题,或者将性能推向极端的试验,我发现我没有一致的确定性方法来判断是否可以仅使用CAS来解决问题。举个例子:
典型的生产者/消费者模型。并发队列只能使用CAS解决问题。
生产者/消费者模型,包含大量更新但消费混合。在这种情况下,如果使用双缓冲,则必须应用读/写锁定;但是,如果我们使用三重缓冲,那么使用CAS基本上是可能的。
粗略地说,我们可以说如果一块逻辑可以被分成几个相互依赖的状态,每个只需要CAS,那么这种逻辑只能通过CAS解决。但是应用于真正的问题似乎要复杂得多,而且我觉得缺乏一种好的方法来划分并确定这种逻辑划分是否可行。
请与我分享您的经验或我不了解的任何方法。
答案 0 :(得分:0)
经过多年使用原子学,这是我的非专业经验法则。
<强>同位强> 要使用原子,所有必须原子改变的数据都需要是连续的。因此,使用原子很难实现双链表,因为您必须同时更新不同节点上的指针。单个链表很简单。
<强>小。强> 小意味着与系统允许的最大原子操作一样小。要使用atomics更新结构中的50个字段,可以创建新结构,然后以原子方式交换指向它的指针。
你不需要任何花哨的东西。 使用单个链接列表进行原子操作时,只能在列表前面添加和删除项目。如果您可以使用哈希表,单个链表,跳过列表或数组,则可以使用原子。 Atomics非常适合构建结构,然后以原子方式交换指向该结构的指针。
您需要细粒度锁定。 例如,使用和原子哈希表,您可以“锁定”桶级别而不是列表级别。我想你每桶可以有一个互斥锁。
<强>速度强> 与原子相比,互斥体是神可怕的慢。每次调用malloc时编写一个锁定互斥锁的内存分配器会很糟糕。我在大约3年前对互斥量与原子进行了基准比较,并且出现了40倍的放缓。
混合搭配! 我使用互斥锁的地方,原子会在屁股和混淆中完全痛苦。我尝试将这些情况限制为执行不多的代码,因此我不会为性能损失付出代价。
所有这些限制都说我很容易在所有热点中使用原子,只需要很少回到互斥体。