views:

101

answers:

4

Hi

I implementing a high performance thread safe component, using no lock statements, only volatile and Interlocked are used for performance reasons.

I have volatile reference-type member in a class, that contains thread safe instance. This instance is thread safe only for a couple of operations, and not for another. Because of that and for performance reasons, in some cases i prefer creating new instance instead of updating the original, and it really working faster, especially because i dont using any lock statements.

So the volatile member can be replaced in any time to another instance, the volatile keyword ensures that there will not be any problem with that in multithreaded environment.

This of course working very well, but the only problem with that is the garbage collection of the old instances. When tested my component for performance, i found that it spending too much time in garbage collection the released instances.

Now i searching a way to recycle the old instances. The problem is that i can't just take the old instance when replacing and just reset it's state because there may be another threads that still using this instance and i can't found a way (without lock) that guaranties that noone using this instance anymore.

How can i guaranty that there is no thread that using the old instance without lock statements? (volatile and Interlocked are preferred)

Thanks.

+1  A: 

The problem is that any thread can take a reference to object onto the stack, and then do whatever they want with it. There's no way of preventing this for the non-threadsafe operations without using an overall lock.

Generally, you shouldn't try to work against the .NET garbage collector - it'll be better to find out why GCs are taking so long, and optimize for that (don't create so many instances in the first place, maybe an O(n^2) operation creating lots of instances?) rather than trying to re-use instances in a thread-safe way.

thecoop
the many instances are created by design, it should be like that. if i could recycle the instances so no garbage collection will be needed at all.
DxCK
A: 

You are asking if something exists that will tell you if it is safe to do an operation on an object in a multi-threaded application. That is the definition of a lock. If using the structure that is provide by .NET is not fast enough, maybe you should consider changing to a complied language that will run faster.

unholysampler
i want to recycle because i dont want to use lock from the first place for performance reasons. i dont asking to completely synchronize access to an instance, i just want to wait until all others are done with the instance and then do whatever i want with it, this definition is less generic than the original lock definition and i'm sure i can be done without lock.
DxCK
+2  A: 

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

mfeingold
I thought about counting, but the problem is that take a reference and increment a counter can't be an atomic operation, so this can create race condition in case that a thread just took a reference and not incremented the counter yet, another thread finds that the counter is zero and recycling the instance while the previous thread incrementing the count and doing other stuff.
DxCK
It's not true that access to volatile implies a barrier, assuming that volatile has the same semantics in the C# memory model as Java - processors such as all x86 CPUs have strong enough memory visibility semantics that *read* access to a volatile needs no special semantics at the CPU level - only writes need a barrier/interlocked instruction (of course at the bytecode level both reads and writes have special semantics wrt allowed re-orderings and so on).
BeeOnRope
A: 

You could ressurect the object from the dead, i.e. when your objects are finalized you actually make them alive again. This has the benefit, that at this point in their lifecycle, there cannot be any reference to them, otherwise they would have never been applicable for finalize in the first place. For more details look for the "Ressurection" chapter in this article.

Now, if that really buys you any performance, or if it is worth doing it, I can't tell ;-)

Christian.K