简体   繁体   中英

Why does the lock object have to be readonly?

When implementing a lock, I used to create a private object inside of my class:

If I want to be sure that it is locked in the thread that created my class:

private object Locker = new object();

If I want to be sure that it will be locked for all threads inside my application:

private static object Locker = new object();

But here: Why does the lock object have to be static?

and in a number of other questions, everyone says that the object has to be readonly . I haven't found the reason - not even in MSDN or JavaDoc.

As I use this kind of construction quite often, could someone explain to me why should I use readonly ?

Thanks!

If I want to be sure that it will be locked for all threads inside my application:

The lock object has to be static, if it locks access to static state.
Otherwise it has to be instance, because there's no need to lock state of one class instance, and prevent other threads to work with another class instance at the same time.

everyone says that the object has to be "readonly" I didn't found the reason

Well, it doesn't have to be. This is just a best practice, which helps you to avoid errors.

Consider this code:

class MyClass
{
    private object myLock = new object();
    private int state;

    public void Method1()
    {
        lock (myLock)
        {
            state = // ...
        }
    }

    public void Method2()
    {
        myLock = new object();
        lock (myLock)
        {
            state = // ...
        }
    }
}

Here Thread1 can acquire lock via Method1 , but Thread2, which is going to execute Method2 , will ignore this lock, because lock object was changed => the state can be corrupted.

它不必是只读的,但这是一个很好的做法,因为它可以避免您意外更换它,这可能会导致一些难以追踪的错误。

I guess what meant is "a variable referencing a lock object should be read only".

You lock on a lock object that variable references, not on a variable itself. Ie having

private object Locker = new object();

you lock on that new object(), not on Locker field. Then, if you replace the value of the field with a reference to another object, say

Locker = new object();

and lock on it, you are locking on two different objects , and that defeats the purpose of the locking, because you do not get a synchronized access now.

The object should ideally be readonly so that it cannot be changed to point to another object. If you took a lock on an object, then another thread changes the object, if, then another thread comes along, and tries to take a lock on this object, the object in question would not be the same, so the original lock would be invalidated.

This would be a very rare case. But if you had a lock on the object, and another thread waiting on that object, if the locking thread calls Monitor.Pulse, the waiting thread is awoken, and can take the lock on the object. In that period of time between being woken and taking the lock, another thread could change the object that is referenced in the lock, and so the waiting thread would take a lock on a different object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM