C Parallel Garbage Collector,如何避免锁定主线程

时间:2011-08-06 06:12:55

标签: c multithreading garbage-collection pthreads yield

我正在开发一个并行垃圾收集器。它是三标记收集器,通常使用白色 - >灰色 - >黑色。当收集器将对象从灰色移动到黑色时,它会下降到对象中以便将子项标记为灰色。此时,它需要取出一个锁,以防止在读取对象时对象在主线程中发生更改。由于为每个对象提供一个独立的锁是一个疯狂的内存需求,我有一个锁(每个非gc线程)必须在修改对象之前锁定。在读取对象之前,GC将使用该线程锁定。

因此,GC将从一个线程迭代对象并在读取子进程之前取出一个锁,然后在下一次迭代之前释放锁。我想确保GC不会占用很多锁。对我来说,显而易见的解决方案似乎是在释放锁之后的'yield',以便主线程可以在等待锁定时继续。垃圾收集器不是优先级线程,如果完成工作需要很长时间并不重要。

但是,我正在使用pthreads(linux),当我谷歌sched_yield()函数时,我发现它被认为是有害的。大多数结果都是对它应该做什么的争论。简而言之,似乎可以说如果你使用sched_yield()你做错了什么。

http://www.technovelty.org/code/c/sched_yield.html似乎提出了另一种选择,但我无法掌握算法的关键点,或者具体说明如何将其应用于我的需求。

1 个答案:

答案 0 :(得分:2)

关于具有每个对象锁定的主题,我用来保持空间要求受限的一种方法是使用一个循环的锁定数组(其中包含一些大而可管理的锁定数,例如8096) 。然后你把一个仲裁器放在它前面,将一个给定的对象与数组中的下一个锁相关联(或者如果该对象已经与数组中的一个锁相关联,那么仲裁器将该锁提升回数组的前面) 。

这为您提供了为每个对象保持单独锁定的性能优势,而没有为每个不同对象实例实际拥有明确锁定对象的疯狂空间要求。当然,您必须调整算法的锁定数量,以确保循环遍历整个圆形锁定数组所花费的时间总是小于处理对象所需的时间。

或许更好的方法是让仲裁器更像是一个资源管理器,用于“检出”和“签入”的锁池。然后当有人请求检出锁时,只要一个人在池中可用(或者已经检出同一个对象实例),仲裁者就可以立即发出一个锁,否则它必须阻塞,直到某个其他线程检查锁定为止in。

无论如何,我不确定这是否直接适用于您的问题,我只想指出在“每个对象一个锁定”和“只有一个锁定”之间还有其他可行的选项可能是在您的使用模式中很有用。