0

我实现了一个高性能线程安全组件,不使用锁定语句,出于性能原因仅使用 volatile 和 Interlocked。

我在一个包含线程安全实例的类中有 volatile 引用类型成员。此实例仅对几个操作是线程安全的,而对另一个则不是。因此,出于性能原因,在某些情况下,我更喜欢创建新实例而不是更新原始实例,而且它确实工作得更快,特别是因为我不使用任何锁定语句。

因此 volatile 成员可以随时替换为另一个实例, volatile 关键字确保在多线程环境中不会出现任何问题。

这当然工作得很好,但唯一的问题是旧实例的垃圾收集。在测试我的组件的性能时,我发现它在垃圾收集释放的实例上花费了太多时间。

现在我正在寻找一种方法来回收旧实例。问题是我不能在替换时只使用旧实例并重置它的状态,因为可能有另一个线程仍在使用这个实例,我找不到一种方法(没有锁)来保证没有人使用这个实例了。

我如何保证没有线程使用没有锁语句的旧实例?(volatile 和 Interlocked 是首选)

谢谢。

4

4 回答 4

2

What you are trying to implement here looks so much like reference counting (remember COM?). You probably can do this with increments / decrements - just keep a reference counter right next to your reference.

The only problem with this technique is that it relies on the object consumers to be decent with object usage. This makes the code very fragile.

Another question is that AFAIK the main performance problem with locks is not the lock iteself but rather the memory barrier it implies. The point is that every acces to a volatile variable does the same. In other words I do not thnk you gained anything replacing locks with volatile variables

于 2009-12-22T22:49:21.073 回答
1

问题是任何线程都可以将对象的引用放到堆栈上,然后用它做任何他们想做的事情。如果不使用整体锁,就无法防止非线程安全操作发生这种情况。

通常,您不应该尝试使用 .NET 垃圾收集器 - 最好找出 GC 需要这么长时间的原因,并为此进行优化(首先不要创建这么多实例,也许O(n^2) 操作创建大量实例?)而不是尝试以线程安全的方式重用实例。

于 2009-12-22T22:38:09.273 回答
0

您正在询问是否存在某些东西,它会告诉您在多线程应用程序中对对象执行操作是否安全。这就是锁的定义。如果使用 .NET 提供的结构不够快,也许您应该考虑更改为运行速度更快的编译语言。

于 2009-12-22T22:47:39.670 回答
0

您可以使对象从死里复活,即当您的对象最终确定时,您实际上使它们再次活着。这样做的好处是,在它们生命周期的这一点上,不能有对它们的任何引用,否则它们一开始就不会适用于 finalize。有关更多详细信息,请查看本文中的“复活”一

现在,如果这真的能为你带来任何表现,或者是否值得这样做,我不能说;-)

于 2009-12-23T05:54:05.980 回答