What to pass to the lock keyword? - c#

What is the difference (if any) between using
void MethodName()
{
lock(this)
{
// (...)
}
}
or
private object o = new object();
void MethodName()
{
lock(o)
{
// (...)
}
}
?
Is there a difference in performance? Style? Behaviour?

lock(this) will lock on the "current" object.
Locking on "this" is usually a bad idea as it exposes the lock to other code; I prefer to have a readonly field, like this:
public class Foo
{
private readonly object padlock = new object();
public void SomeMethod()
{
lock(padlock)
{
...
}
}
}
That way all calls to SomeMethod (and anything else in Foo which locks on padlock) will lock on the same monitor for the same instance of Foo, but nothing else can interfere by locking on that monitor.
In reality, unless you're dealing with "rogue" code, it's unlikely that other code will actually lock on the reference to an instance of Foo, but it's a matter of encapsulation.

The difference is that anyone can lock on your instance, but only you can lock on a private object.
This helps prevent deadlocks.
For example:
Let's say that Microsoft used lock(this) in the Control class.
Then, if someone else locks on a Control instance, his lock would prevent the code in Control from running, which is not what he wants.
This is particularly bad if you lock on types that are shared across AppDomains

The pattern I usually follow is this, for a class declared static....
public static class SomeClass{
private static object objLock = new object();
....
public static object SomeProperty{
get{
lock(objLock){
// Do whatever needs to be done
}
}
set{
lock(objLock){
}
}
}
}
Likewise for a normal class I would follow this pattern:
public class SomeClass{
private readonly object objLock = new object();
....
public object SomeProperty{
get{
lock(objLock){
// Do whatever needs to be done
}
}
set{
lock(objLock){
}
}
}
}
In that way, no one can lock on my instance and will prevent deadlocks from occuring...
Edit: I have amended this article to make it clearer with regards to the code where the basis of the static lock would be used and for a normal class... Thanks Steven and Dalle for their point outs...

There is a difference in scope and there can be a difference in behavior
(incidentally, using "this" is not recommended by MS
// in this case, your lock object is public, so classes outside of this can lock on the same thing
lock(this) {}
// in this case, your lock is private, and only you can issue a lock statement against it
private object lockobj = new object()
..
lock(this.lockobj) {}
// this one is WRONG -- you willget a new object instance every time, so your lock will not provide mutual exclusion
void SomeMethod()
{
// using a local variable for a lock -- wrong
object obj = new object();
lock(obj) {}
}

Related

How to run the code only once in multithreading environment? [duplicate]

The following code block, performs loading of an object in C#.
public bool IsModelLoaded { get; set; }
public override MyObject Load()
{
if (!IsModelLoaded)
{
Model = MyService.LoadMyObject(Model);
IsModelLoaded = true;
}
return Model;
}
My intention is to run this block only once, and hence loading the Model only once. Nevertheless, this code block runs twice from 2 different threads.
How can I make sure that this block runs only once? (on multiple threads).
Use the Lazy<T> Class:
private readonly Lazy<MyObject> myObject;
public MyClass()
{
myObject = new Lazy<MyObject>(() =>
{
return MyService.LoadMyObject();
}, LazyThreadSafetyMode.ExecutionAndPublication);
}
public bool IsModelLoaded
{
get { return myObject.IsValueCreated; }
}
public override MyObject Load()
{
return myObject.Value;
}
Simplest would be to add
[MethodImpl(MethodImplOptions.Synchronized)]
public override MyObject Load()
{
//snip
}
but be aware this puts a lock on the entire object, not just the method. Not really great practice.
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx
Synchronized
Specifies that the method can be executed by only one thread at a time. Static methods lock on the type, whereas instance methods lock on the instance. Only one thread can execute in any of the instance functions, and only one thread can execute in any of a class's static functions.
I are trying to implement singleton pattern. But your version is not thread safe. Read more here: http://www.dofactory.com/Patterns/PatternSingleton.aspx. Try to use this implementation:
public sealed class Singleton
{
static Singleton instance=null;
static readonly object padlock = new object();
Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance==null)
{
instance = new Singleton();
}
return instance;
}
}
}
}
If you want to write thread safe code and make sure that the block runs only once, you can write like this:
private System.Object lockThis = new System.Object();
public override MyObject Load()
{
lock (lockThis) {
if (!IsModelLoaded)
{
Model = MyService.LoadMyObject(Model);
IsModelLoaded = true;
}
}
return Model;
}
Action myCodeBlock = ()=>
{
//do your job
//...
myCodeBlock = ()=>{};
}
After calling myCodeBlock() once it will be rewritten by method that does nothing. You still need to make sure this metod is called safely - use lock or whatever.
You can use lock Statement (C# Reference)
Create a static object (like a boolean) that determines if the code has ran or not by putting it in an if statement :)
EDIT: I'm not sure if this is threadsafe, so it might not be the solution for you.

Will lock prevent changes done via reflection

Assume a class SomeClass with private static field like this. The access to this field is synchronized using lock.
private static SomeClass _instance
private static object _sync = new object();
public static SomeClass Instance
{
get
{
lock (_sync)
{
if (_instance == null)
{
_instance = Create();
}
return _instance;
}
}
}
When another code from different thread will try to set the value of this variable to e.g. null using reflection, will the lock prevent this and let the reflection call wait until the lock was released?
E.g. something like this:
Type type = typeof(SomeClass);
string fieldName = "_instance";
object value = null;
FieldInfo field = type.GetField(fieldName, true);
field.SetValue(null, value);
No, lock will not prevent any access that does not go through locking the same resource. Since reflection will not go through lock, you will get race conditions.
Here is (slightly different from your code but nontheless doing same thing) what I mean→
void SetOne(){
lock (_sync){
critical_element = SOME_VALUE;
}
}
void SetTwo(){
critical_element = SOME_ANOTHER_VALUE;
}
Above definitely has race conditions.
Here is my understanding behind the OP's question. I think OP wants to use Singleton pattern and here is a very nice and thread safe implementation. You do not need to deal with locks either. However, some bad users might still set the backing field using reflection.
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton(){}
}

can lock work across multiple objects in c#?

I have been looking for a way to lock a particular piece of code.
namespace x
{
public class y
{
private Object obj = new Object();
private void A()
{
lock(obj)
{
//critical section
}
}
}
}
Upon request my application enters method A from different sources(which uses class Y) and it is seen that lock object is failing to protect the critical section.
I am looking for the way to protect critical section even though multiple objects try to access the piece of code and i do not want to use static lock object.
Please help me.
Lock do the job, but you lock an instance field, it will protect your critical section only for same instance. If you want to lock for all instance, make your flag (Obj) static.
namespace x
{
public class y
{
static private Object obj = new Object();
private void A()
{
lock(obj)
{
//critical section
}
}
}
}

Do not lock on objects with weak identity

How can i resolve this reliability issue(Do not lock on objects with weak identity)?
Should i lock it with "object locker = new object();"?
lock (typeof(ObjectCultures))
{
if (!requestCache.Contains(GetCacheKey(objectId, cultureId)))
{
requestCache.Add(GetCacheKey(objectId, cultureId), responseStr);
}
}
Create a new static instance of an object and lock on that:
private static readonly object locker = new object();
lock (locker)
{
....
}
This is on the assumption you are locking inside a static method (due to your use of typeof(T) instead of the this which is also bad practice).
Obviously if you are inside an instance method remove the static from the declaration.
This article by Jon Skeet will help explain why the issue is being flagged in the first place.
You should lock an object not a type. Declare and instance this object in a main scope of your class, for sample:
public class SomeClass
{
private static readonly object _lock = new object();
public void SomeMethod()
{
lock (_lock)
{
// some code
}
}
}
This code will block all thread that are trying to execute this block and make them wait for finish and then execute the next thread.
Effectively, you need to put the lock in a static object reference. An object typed reference should be enough.
public class X
{
private readonly static _syncLock = new object();
public void DoStuff()
{
lock(_syncLock)
{
// Critical section
}
}
}
Exactly how you should lock.. depends on the context, and the bigger picture of code you are trying to write..
What you do want to avoid, is locking on objects of type indicated in the link you already got -
http://msdn.microsoft.com/en-us/library/ms182290.aspx
Do note that the handful of types listed here is not the full list...
• MarshalByRefObject
• ExecutionEngineException
• OutOfMemoryException
• StackOverflowException
• String
• MemberInfo
• ParameterInfo
• Thread
Full list would include instance of any type which is derived directly or indirectly from any of the above mentioned types..
Note that System.Type extends System.Reflection.MemberInfo
http://msdn.microsoft.com/en-us/library/system.type.aspx
And hence the warning, when using lock (typeof(ObjectCultures))

Lock code section to one entrance at a time

I am trying to restrict access to an singletone object so only one thread
use it at time, Furthermore, I want to prevent from the same thread accessing twice
to the restricted code.
I tried the Lock method and i found out that its dosn't lock the thread that locked her, but only other threads..
as below:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
public class SomeWorker
{
private readonly Timer _doWorkTimer = new Timer(20);
public SomeWorker()
{
InitiateTimer();
}
private void InitiateTimer()
{
_doWorkTimer .Elapsed += DoWorkElapse;
_doWorkTimer .Enabled = true;
}
private void DoWorkElapse(object source, ElapsedEventArgs e)
{
DoSomeWork();
}
private void DoSomeWork()
{
// I know that lock on string is wrong!
// Its just for the example only I
// Its just to make sure all the program is use the same lock..
lock ("ConnectionLock")
{
Console.WriteLine("Lock");
var inst = Singletone.Instance;
// Do Some Work on "inst" ...
Console.WriteLine("Unlock");
}
}
}
The result in the console for example is:
.
.
.
Lock
Unlock
Lock
Lock
Unlock
.
.
.
As we can see, 2 Lock comments shows one after another
So its mean that the "DoSomeWork()" accessed twice by the timer thread.
Anyone have any idea how to make this lock work?
Other Sync methods maby?
thanx.
You aren't doing your locking properly (and to top it off you are taking a lock on a string which is a big no-no). To save time, please read this article from Jon Skeet and implement one of the patterns to save yourself a headache.
In your code you have
public static Singletone Instance()
{
if (_instance == null)
{
lock (_instance)
{
if (_instance == null)
{
_instance = new Singletone ();
}
}
}
return _instance;;
}
Think about it. if (_instance == null) you do lock (_instance). So you lock using null. That's not good at all.
In MSDN lock Statement (C# Reference) the given example of how to use lock is:
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
I guess you should follow it and have a separate object to use it as a lock.
And secondly, thread syncronization primitives are used to separate access to shared resources for different threads. If you need to separate access from one thread, you simply need to use flags. Something like this:
bool isBusy = false;
public static void Foo()
{
if (!isBusy)
{
isBusy = true;
try
{
//do the job
}
finally
{
isBusy = false;
}
}
}
Here you should understand that you simply skip the "locked-by-flag" code. On the contrary if you want to make the thread wait for itself, especially in a multithreading application, I guess it looks like it should be redesigned.
The easiest way to implement a singleton in .NET is:
public class Singleton : IDisposable
{
private readonly static Singleton _instance = new Singleton();
private readonly static object lockObject = new object();
static Singleton()
{
}
private Singleton()
{
InitiateConnection();
}
public static Singleton Instance
{
get { return _instance; }
}
/// <summary>
/// Method that accesses the DB.
/// </summary>
public void DoWork()
{
lock (lockObject)
{
//Do Db work here. Only one thread can execute these commands at a time.
}
}
~Singleton()
{
//Close the connection to DB.
//You don't want to make your singleton class implement IDisposable because
//you don't want to allow a call to Singleton.Instance.Dispose().
}
}
Read the excellent article on Singleton Pattern implementations in .NET that Bryan suggested in his answer. The above implementation is based on the fourth version described in the article. The CLR guarantees that the construction of the static field will thread-safe hence you do not need locking there. However you will need locking if your object has state (fields) that can be changed.
Note that there is a private readonly object used for ensuring mutual exclusion on the DoWork method. This way a single thread can call DoWork at a time. Also note that there is no way that the same thread can call this method twice at the same time since a thread executes instructions sequentially. The only way this method could be called twice from a single thread is if inside DoWork you call another method that eventually calls DoWork. I can't see the point of doing this and if you do then take care to avoid stack overflows. You could follow the suggestion of Konstantin and use a flag but IMHO you should redesign DoWork to do just one thing and avoid scenarios like these.

Categories