I have a class and its properties; the access to these properties is very frequently done by different threads.
It is more efficient use the same object (for the lock statement) for each property?
private readonly object padlock = new object();
private string name;
private int age;
public string Name
{
get
{
lock(padlock)
return name;
}
set
{
lock(padlock)
name = value;
}
}
public int Age
{
get
{
lock(padlock)
return age;
}
set
{
lock(padlock)
age = value;
}
}
Or to use a different object for each property?
private readonly object padlockName = new object();
private readonly object padlockAge = new object();
private string name;
private int age;
public string Name
{
get
{
lock(padlockName)
return name;
}
set
{
lock(padlockName)
name = value;
}
}
public int Age
{
get
{
lock(padlockAge)
return age;
}
set
{
lock(padlockAge)
age = value;
}
}
The second version makes any sense?
I hesitate to even answer the question you've asked, because I doubt that either of these locking patterns will ensure correctness in your application. They don't ensure that the object as a whole is kept in a consistent state - they just ensure that individual properties are not updated concurrently. To put it another way, you've implemented atomic reads and writes in a roundabout way.
For example, say you had an operation that would increment Age
. If two different threads did that at once, the final result could be (Age + 1) or (Age + 2).
You should most likely remove locking from within the object, and have callers deal with concurrency issues as appropriate. One easy solution is to lock the entire object for the duration of their interaction with it. eg:
lock(myObj){
myObj.Age++;
myObj.Name = "Bill";
}
Update
To expand on my middle paragraph, the reason that running Age++
on two different threads could give different results is because the ++
operator is not atomic. It is roughly equivalent to this.
int temp = Age;
temp = temp + 1;
Age = temp;
If two threads ran the same thing, it could execute in order like this (for clarity I've changed names of the temp variables):
int temp1 = Age; //thread 1
int temp2 = Age; //thread 2
temp1 = temp1 + 1; //thread 1
temp2 = temp2 + 1; //thread 2
Age = temp1; //thread 1
Age = temp2; //thread 2
The purpose of locking is to ensure that one thread runs the entire read-increment-write sequence before the other thread does. But your locking scheme doesn't do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With