我实现了一个高性能的线程安全组件,没有使用锁定语句,出于性能原因,只使用了volatile和Interlocked。
我在类中有volatile的reference-type成员,它包含线程安全实例。 此实例仅适用于几个操作的线程安全,而不适用于另一个操作。 由于这一点,并且出于性能原因,在某些情况下我更喜欢创建新实例而不是更新原始实例,并且它确实更快,特别是因为我没有使用任何锁定语句。
因此volatile变量可以随时替换为另一个实例,volatile关键字确保在多线程环境中不存在任何问题。
这当然工作得很好,但唯一的问题是旧实例的垃圾收集。在测试我的组件的性能时,我发现它在垃圾收集中花费了太多时间来释放实例。
现在我正在寻找回收旧实例的方法。问题是我不能只是在更换时采用旧实例,只是重置它的状态,因为可能还有另一个线程仍在使用这个实例而且我找不到一种方法(没有锁定)保证没有人使用这个实例了。
我怎样才能保证没有使用没有锁定语句的旧实例的线程? (首选volatile和Interlocked)
感谢。
答案 0 :(得分:2)
您在这里尝试实现的内容与引用计数(请记住COM?)非常相似。您可以通过增量/减量来执行此操作 - 只需在参考旁边保留一个参考计数器。
这种技术的唯一问题是它依赖于对象消费者对对象的使用是否体面。这使得代码非常脆弱。
另一个问题是,AFAIK锁的主要性能问题不是锁自身,而是它暗示的内存障碍。关键是每次对volatile变量的访问都是一样的。换句话说,我并不认为你获得了任何用volatile变量替换锁的东西
答案 1 :(得分:1)
问题是任何线程都可以将对象的引用引入堆栈,然后随意执行任何操作。如果不使用整体锁定,就无法阻止非线程安全操作。
通常情况下,您不应该尝试对抗垃圾收集器 - 最好找出为什么GC需要这么长时间,并为此进行优化(不要在第一时间创建这么多实例) ,也许是一个O(n ^ 2)操作创建大量实例?)而不是尝试以线程安全的方式重用实例。
答案 2 :(得分:0)
您正在询问是否存在可以告诉您是否可以安全地对多线程应用程序中的对象执行操作的内容。这就是锁的定义。如果使用.NET提供的结构不够快,也许您应该考虑更改为运行速度更快的编译语言。
答案 3 :(得分:0)
你可以从尸体中重新确定对象,即当你的对象敲定时,你实际上让它们再次活着。这样做的好处是,在他们的生命周期的这个阶段,不能有任何参考,否则他们从来没有适用于最终确定。有关详细信息,请查看this文章中的“Ressurection”章节。
现在,如果真的给你带来任何表现,或者值得这样做,我说不出来; - )