【发布时间】:2010-12-01 01:04:05
【问题描述】:
我试图在 C 中实现一个(特殊类型的)双向链表,在 pthreads 环境中,但仅使用 C 包装的同步指令,如原子 CAS 等,而不是 pthread 原语。 (列表的元素是固定大小的内存块,几乎肯定不能在其中容纳pthread_mutex_t 等。)我实际上并不需要完整的任意双向链表方法,只需:
- 在列表末尾插入
- 从列表开头删除
- 根据指向要删除的成员的指针在列表中的任意点删除,该成员是从不是通过遍历列表的来源获得的。
因此,描述这种数据结构的更好方法可能是队列/先进先出,可以删除队列中的项目。
是否有标准的方法来同步?我陷入了可能的死锁问题,其中一些可能是所涉及的算法所固有的,而另一些可能源于我试图在受限空间中工作的事实,而其他限制我能做什么。
编辑:特别是,如果要同时移除相邻对象,我会卡在该怎么做。大概在删除一个对象时,您需要获取列表中前一个和下一个对象的锁,并更新它们的下一个/上一个指针以指向另一个。但是如果任一邻居已经被锁定,这将导致死锁。我试图找出一种方法,使发生的任何/所有删除都可以遍历列表的锁定部分并确定当前正在删除的最大子列表,然后锁定与该子列表相邻的节点,以便整个子列表被整体删除,但我的头开始受伤了.. :-P
结论(?):接下来,我确实有一些我想开始工作的代码,但我也对理论问题感兴趣。每个人的答案都非常有帮助,并结合了我在这里表达的约束之外的细节(你真的不想知道要删除的指向元素的指针来自哪里以及那里涉及的同步!)我决定暂时放弃本地锁定代码并专注于:
- 使用大量较小的列表,每个列表都有单独的锁。
- 在获取锁之前尽量减少持有锁和在内存中戳的指令数量(以安全的方式),以减少在持有锁时出现页面错误和缓存未命中的可能性。
- 测量人为高负载下的争用并评估此方法是否令人满意。
再次感谢所有给出答案的人。如果我的实验不顺利,我可能会回到概述的方法(尤其是 Vlad 的方法)并重试。
【问题讨论】:
-
我相信只要不关心列表的一致性,用双链表就可以做到。添加或删除的对象可能可见或不可见,具体取决于您在列表中移动的方向。
-
@R:固定长度的缓冲区(循环使用)对你没有好处?
-
可悲的是,我找不到让它与固定长度的循环缓冲区一起工作的方法。我从一开始就想这样做,因为它会更简单,性能也会更好......
-
@R: 你的意思是你的意思是你找不到一种方法来让一个无锁的固定长度循环缓冲区工作,还是你找不到一种方法来让这样一个缓冲区满足您的应用程序的需求?
-
我找不到让它满足要求的方法。我需要一种方法来提前确保循环缓冲区已经被充分扩大,以满足所有可能的未来插入,直到下一个点内存重新分配成为可能(在插入点是不可能的)。
标签: c synchronization pthreads linked-list