C并行垃圾收集器,如何避免锁定主线程

标签 c multithreading garbage-collection pthreads yield

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

因此,GC 将从线程中迭代对象并在读取子对象之前取出锁,然后在下一次迭代之前释放锁。我想确保 GC 不会过多占用锁。对我来说,最明显的解决方案似乎是在释放锁后立即“让步”,这样主线程在等待锁时可以继续。垃圾收集器不是优先线程,完成它的工作需要很长时间也没关系。

但是,我使用的是 pthreads (linux),当我用 google 搜索 sched_yield() 函数时,我发现它被认为是有害的。大多数结果是关于它甚至应该做什么的争论。简而言之,如果您使用 sched_yield() 似乎可以说您做错了什么。

http://www.technovelty.org/code/c/sched_yield.html似乎提出了一个替代方案,但我无法掌握算法的关键点,或者具体如何将其应用于我的需求。

最佳答案

关于拥有每个对象锁的主题,我用来限制空间需求的一种方法是拥有一个循环锁阵列(其中有一些大但可管理数量的锁,比如 8096) .然后在它前面放置一些仲裁器,将给定对象与数组中的下一个锁相关联(或者如果该对象已经与数组中的锁相关联,则仲裁器将该锁提升回数组的前面) .

这为您提供了为每个对象保留一个单独的锁的性能优势,而不需要为每个不同的对象实例实际拥有一个不同的锁对象的疯狂空间需求。当然,您必须根据算法调整锁的数量,以确保循环遍历整个锁循环阵列所花费的时间始终少于处理一个对象所需的时间。

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

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

关于C并行垃圾收集器,如何避免锁定主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6965142/

相关文章:

c# - 如何让 NUnit 测试等待线程完成?

scala - 大量 Scala Actor 的 gc

java - Apache POI : garbage collection does not free memory [Java]

c - Objective C 版本的 explode()?

java - 使用继承使类线程安全

c - 如何只初始化一次信号量?

java - 如何避免GC暂停?

c - 我没有正确处理多个 block

c++ - Visual C++ 和 gcc 一样强大吗?

c - 验证 scanf 的输入