Can I use a locked object?

What happens if I call Dispose() on a locked object?

 lock (obj) { obj.Dispose(); } 

And what happens if I missed the call to Monitor.Exit() in this case:

 Monitor.Enter(obj); obj.Dispose(); 
+6
source share
5 answers

What happens if I call Dispose () on a locked object?

Firstly, the object itself is not locked (protected) to begin with. The link used in the lock key is used to mark or mark a section of code that should not be launched simultaneously with any other (or the same) part of the code that used the same object link. This does not actually affect the object itself. This is a fairly common misconception about how locks work in .NET.

In this context, calling Dispose is no different than calling any other method. Nothing special happens. It just means that two different threads cannot execute Dispose at the same time. What you do is not only acceptable, but really recommends if the class is not thread safe.

And what happens if I miss the call to Monitor.Exit () in this case:

You should always let go of locks. Keeping in mind that locks do not affect an object link, it should be easier to understand that you will leave the lock in the acquired state. It does not matter that the object is located. Remember that Monitor (or lock ) does not lock or protect the object itself. It only marks or marks a section of code. If a thread tries to obtain a lock with the same object again, this thread will be forced to wait indefinitely, which can lead to a deadlock.

A more interesting question: can this lead to a memory leak. Does Monitor.Enter root of an object? The answer is no. This can be demonstrated in the following example.

 public class Program { public static void Main(string[] args) { var foo = new Foo(); Monitor.Enter(foo); foo = null; GC.Collect(); GC.WaitForPendingFinalizers(); Console.ReadLine(); } } internal class Foo { ~Foo() { Console.WriteLine("~Foo"); } } 

If you compile and run this, you will see that "~ Foo" is printed. This suggests that Monitor.Enter does not contain a link inside. Therefore, although it is not recommended to skip the Monitor.Exit call, you may feel some comfort knowing that it will not cause a memory leak. 1


1 Actually, this may not be entirely true. Although it is fairly easy to demonstrate that a managed memory leak cannot be otherwise, in an unmanaged area it can be different. Despite the SSCLI code, we really don't know what Monitor.Enter does internally. Perhaps it allocates one additional array slot (or something else) in an unmanaged heap or stack. I would like to think that Microsoft has considered this obscure scenario, but who knows. The fact is that the calls Monitor.Enter and Monitor.Exit should always be paired so that you do not have to worry about it.

+5
source

Dispose implementations are usually not thread safe.

This is because you should not dispose of the object as long as there are links that can be used. This means that you should not get rid of the object referenced by any other thread.

IDisposable / Dispose not a method for controlling the lifetime of an object, either in general or in streams; it is a paradigm for releasing an object's resource after the end of its life cycle. (The using statement is the idiom / paradigm to use, where the true lifetime of the object is the scope.)

So, if you call dispose and another thread is blocked, something is already wrong.

+6
source

The Dispose paradigm is different from lock . You can safely dispose of the object on which you are currently holding a mutual exclusion lock; however, you should still release the lock after this. If you do not, the other threads that call Monitor.Enter for the object (now located) will block indefinitely.

+4
source

For your first question - it happens that only one threat at a time can call Dispose (). For your second question - if multiple threads run this code, the first one will call the Dispose method. The rest will be blocked forever.

There is nothing special about the dispose method. This is similar to any other method, except that it participates in some kind of syntactic sugar (for example, using instructions).

+1
source

You can always lock an existing object, the Dispose method will not delete your object, so the object reference still exists. The Dispose() method does not affect the instance of the object.

+1
source

Source: https://habr.com/ru/post/954938/


All Articles