Why Does the Lock Object Have to Be Static

Why does the lock object have to be static?

It isn't "very common to use a private static readonly object for locking in multi threading" - rather, it is common to use a lock at the appropriate / chosen granularity. Sometimes that is static. More often, IMO, it isn't - but is instance based.

The main time you see a static lock is for a global cache, or for deferred loading of global data / singletons. And in the latter, there are better ways of doing it anyway.

So it really depends: how is Locker used in your scenario? Is it protecting something that is itself static? If so, the lock should be static. If it is protecting something that is instance based, then IMO the lock should also be instance based.

Why does the lock object have to be readonly?

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.

Does a static lock object need to be final when using a synchronized(lock object) block?

Using the final in this context is only a good practice.

You can synchronize using any object, final or non final, static or non static.

Using together final and static will give you the security that nobody will synchronize the same code on a different lock. Without using the final you are not sure that somewhere in the code that variable is not reassigned.

Generally speaking using final for a variable that is never reassigned after inited it's a good programming practice. It improves readability because who reads your code knows that this variable will never been reassigned also without reading the full code.

Do lock objects in Java need to be static?

Depends on in which context they are to be used. If you want a per-instance lock, then leave static away. If you want a per-class lock, then use static. Further indeed keep it final.

C# lock a private static object

So if it's a static object, instead of a string, will it have the problem when the same method is called multiple times

Not exactly. Strings are special, they can be interned. You can't control their visibility like that of other objects.

The basic guidelines:

  • keep your lockObject in a close 1-on-1 relationship with the protected resource. In numbers, scope and lifetime. So use a static lockObject to protect static data.
  • keep the lockObject as private as possible, exposing it increases the risk of deadlocks. For that reason also avoid locking on Types and strings.

because it's the same static object so they are actually sharing the lock?

All code that accesses a shared resource has to share (lock on) the same lockObject instance. A private lock won't work.

Lock on non-static method

Locking on a static object in a non-static method is fine. The static object just means that there is one single lock for all your instances of the type.

If you use a class level field you have one lock per instance of your type.

Which one you choose depends on what resource you are protecting from concurrent access. For example if you have a static resource (say, a collection) then the lock protecting that resource must also be static.

Difference between lock(this) and a lock on static object

There could be a big difference. The biggest difference between the two is that the first example uses a single object to lock on (hence the static keyword) while the this keyword in the second example implies locking on an instance. There could therefore be a big difference from a performance perspective and even from a correctness perspective, but that depends on the code inside the lock.

When all you need is to synchronize access to instance level fields, you should not use the static keyword, since that will synchronize the code itself, instead of the data (which could cause an unneeded performance hit). Of course, if the data itself is static (class level data instead of instance level data), you need to use the static keyword. On the other hand, when you use the this keyword to lock, while you're accessing shared / static resources, you will (of course) have a correctness problem, since synchronization is on an instance basis and multiple instance will still be able to access the shared data at the same time.

And there is another problem, but the difference is much smaller than for the previously noted differences. The first example uses a privately declared object to lock on, while the other uses the this pointer, which is the reference to the object of that instance method itself. Because this reference is publicly accessible to other objects, it is possible for them to lock on it, which could cause deadlocks in rare circumstances. If you're an application developer, I wouldn't worry to much about this (as long as you don't lock on things like System.String or System.Type), but if you are a framework developer, you should certainly not use lock(this), since there is no way to tell in what way application developers will (ab)use your code.



Related Topics



Leave a reply



Submit