1

Suppose I need to clean up some managed resources in a finalizer, or at least record it somewhere in a thread safe way that a clean up is needed. From what I understand, taking locks in a finalizer is strictly verboten but how about the Interlocked class? Is this safe and will it not result in a deadlock?

static int deadentries;
~Item() { Interlocked.Increment(ref deadentries); }
public static T Get(int id, Action<T> init) {
    T ret;
    WeakReference<T> tref;
    if (cache.TryGetValue(id, out tref)) {
        if (tref.TryGetTarget(out ret)) return ret;
        else Interlocked.Decrement(ref deadentries);
    }
    if (deadentries * 2 > cache.Count) {
        // etc. etc.

Also, it seems that all finalizers are run on one thread, is this a guaranteed behavior or just an implementation detail? And if it is just a detail, is this ok to acquire a lock inside finalizers (say, to push jobs in a lock-free queue) provided that the lock will never be taken anywhere else?

user1096188
  • 1,809
  • 12
  • 11

1 Answers1

1

Finalizers being run one one thread is an implementation detail (which is unlikely to ever change because it would violate the very strict compatibility standards that MS upholds. Still not ok to rely on).

Locks are actually OK in finalizers. They might become a performance or correctness problem but that is not due to them being run as part of a Finalizer. Those are general properties of locks. The Interlocked class can be used as well.

Just keep in mind that Finalizers can execute in any order and potentially concurrently. Also not in inverse-dependency-order but in random order.

usr
  • 168,620
  • 35
  • 240
  • 369