Lock in multithreaded App C# - c#

Lets say I have declared a class like this :
public class PersistableObject<TObject> where TObject : class, new()
{
private readonly object objectLocker = new object();
private TObject persistableObject;
public TObject Object
{
get
{
lock (this.objectLocker)
{
return this.persistableObject;
}
}
set
{
lock (this.objectLocker)
{
this.persistableObject = value;
}
}
}
public bool Persist()
{
lock (this.objectLocker)
{
// Do Persist Object in file
}
}
public bool Retrieve()
{
lock (this.objectLocker)
{
// Do Retrieve Object from file
}
}
}
This class is responsible for storing a variable of any type, persist it to a file and retrieve it from a file.
As you can see, I used the same lock (an object) to lock 4 operations :
Getting the actual object
Setting the actual object
Persisting the object to file
Retrieving the object from file
Is this the correct approach from concurrency point of view? Am I completely in the safe zone, considering that this class is used by different threads?
UPDATE :
The most important thing for me here, is only one thread should have access to the object at any given time (no matter it wants to get, set, retrieve or persist it). Considering this in mind, is it the correct approach? will any deadlocks or other nasty things happen?

Thread-safety is a property of the whole system, not of a single class or method. Individual operations on an instance of this class will execute exclusively, but maybe you require multiple operations to be atomic. The class has no way to do that.
So is it thread-safe or not? Only you can tell because only you know how the class is being used. If operations on this class are truly independent, then it is safe.
If all you had do to obtain thread-safety way to just lock every member of any class, then threading would be a simple task. Threading is complex because it touches everything in a cross-cutting manner.

Define "being in the safe zone".
Imagine a piece of code executing on multiple threads using your class to
read an object from a file
modify that object
write that object back to the file
None of the locking you do here will help making that scenario thread-safe.

Related

How to make static method thread safe?

I have written a static class which is a repository of some functions which I am calling from different class.
public static class CommonStructures
{
public struct SendMailParameters
{
public string To { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string Attachment { get; set; }
}
}
public static class CommonFunctions
{
private static readonly object LockObj = new object();
public static bool SendMail(SendMailParameters sendMailParam)
{
lock (LockObj)
{
try
{
//send mail
return true;
}
catch (Exception ex)
{
//some exception handling
return false;
}
}
}
private static readonly object LockObjCommonFunction2 = new object();
public static int CommonFunction2(int i)
{
lock (LockObjCommonFunction2)
{
int returnValue = 0;
try
{
//send operation
return returnValue;
}
catch (Exception ex)
{
//some exception handling
return returnValue;
}
}
}
}
Question 1: For my second method CommonFunction2, do I use a new static lock i.e. LockObjCommonFunction2 in this example or can I reuse the same lock object LockObj defined at the begining of the function.
Question 2: Is there anything which might lead to threading related issues or can I improve the code to be safe thread.
Quesiton 3: Can there be any issues in passing common class instead of struct.. in this example SendMailParameters( which i make use of wrapping up all parameters, instead of having multiple parameters to the SendMail function)?
Regards,
MH
Question 1: For my second method CommonFunction2, do I use a new
static lock i.e. LockObjCommonFunction2 in this example or can I reuse
the same lock object LockObj defined at the begining of the function.
If you want to synchronize these two methods, then you need to use the same lock for them. Example, if thread1 is accessing your Method1, and thread2 is accessing your Method2 and you want them to not concurrently access both insides, use the same lock. But, if you just want to restrict concurrent access to just either Method1 or 2, use different locks.
Question 2: Is there anything which might lead to threading related
issues or can I improve the code to be safe thread.
Always remember that shared resources (eg. static variables, files) are not thread-safe since they are easily accessed by all threads, thus you need to apply any kind of synchronization (via locks, signals, mutex, etc).
Quesiton 3: Can there be any issues in passing common class instead of
struct.. in this example SendMailParameters( which i make use of
wrapping up all parameters, instead of having multiple parameters to
the SendMail function)?
As long as you apply proper synchronizations, it would be thread-safe. For structs, look at this as a reference.
Bottomline is that you need to apply correct synchronizations for anything that in a shared memory. Also you should always take note of the scope the thread you are spawning and the state of the variables each method is using. Do they change the state or just depend on the internal state of the variable? Does the thread always create an object, although it's static/shared? If yes, then it should be thread-safe. Otherwise, if it just reuses that certain shared resource, then you should apply proper synchronization. And most of all, even without a shared resource, deadlocks could still happen, so remember the basic rules in C# to avoid deadlocks. P.S. thanks to Euphoric for sharing Eric Lippert's article.
But be careful with your synchronizations. As much as possible, limit their scopes to only where the shared resource is being modified. Because it could result to inconvenient bottlenecks to your application where performance will be greatly affected.
static readonly object _lock = new object();
static SomeClass sc = new SomeClass();
static void workerMethod()
{
//assuming this method is called by multiple threads
longProcessingMethod();
modifySharedResource(sc);
}
static void modifySharedResource(SomeClass sc)
{
//do something
lock (_lock)
{
//where sc is modified
}
}
static void longProcessingMethod()
{
//a long process
}
You can reuse the same lock object as many times as you like, but that means that none of the areas of code surrounded by that same lock can be accessed at the same time by various threads. So you need to plan accordingly, and carefully.
Sometimes it's better to use one lock object for multiple location, if there are multiple functions which edit the same array, for instance. Other times, more than one lock object is better, because even if one section of code is locked, the other can still run.
Multi-threaded coding is all about careful planning...
To be super duper safe, at the expense of potentially writing much slower code... you can add an accessor to your static class surround by a lock. That way you can make sure that none of the methods of that class will ever be called by two threads at the same time. It's pretty brute force, and definitely a 'no-no' for professionals. But if you're just getting familiar with how these things work, it's not a bad place to start learning.
1) As to first it depends on what you want to have:
As is (two separate lock objects) - no two threads will execute the same method at the same time but they can execute different methods at the same time.
If you change to have single lock object then no two threads will execute those sections under shared locking object.
2) In your snippet there is nothing that strikes me as wrong - but there is not much of code. If your repository calls methods from itself then you can have a problem and there is a world of issues that you can run into :)
3) As to structs I would not use them. Use classes it is better/easier that way there is another bag of issues related with structs you just don't need those problems.
The number of lock objects to use depends on what kind of data you're trying to protect. If you have several variables that are read/updated on multiple threads, you should use a separate lock object for each independent variable. So if you have 10 variables that form 6 independent variable groups (as far as how you intend to read / write them), you should use 6 lock objects for best performance. (An independent variable is one that's read / written on multiple threads without affecting the value of other variables. If 2 variables must be read together for a given action, they're dependent on each other so they'd have to be locked together. I hope this is not too confusing.)
Locked regions should be as short as possible for maximum performance - every time you lock a region of code, no other thread can enter that region until the lock is released. If you have a number of independent variables but use too few lock objects, your performance will suffer because your locked regions will grow longer.
Having more lock objects allows for higher parallelism since each thread can read / write a different independent variable - threads will only have to wait on each other if they try to read / write variables that are dependent on each other (and thus are locked through the same lock object).
In your code you must be careful with your SendMailParameters input parameter - if this is a reference type (class, not struct) you must make sure that its properties are locked or that it isn't accessed on multiple threads. If it's a reference type, it's just a pointer and without locking inside its property getters / setters, multiple threads may attempt to read / write some properties of the same instance. If this happens, your SendMail() function may end up using a corrupted instance. It's not enough to simply have a lock inside SendMail() - properties and methods of SendMailParameters must be protected as well.

Locking to make a class threadsafe with a C# example or is this class threadsafe?

I am trying to investigate locking to create a threadsafe class and have a couple of questions. Given the following class:
public class StringMe
{
protected ArrayList _stringArrayList = new ArrayList();
static readonly object _locker = new object();
public void AddString(string stringToAdd)
{
lock (_locker) _stringArrayList.Add(stringToAdd);
}
public override string ToString()
{
lock (_locker)
{
return string.Join(",",string[])_stringArrayList.ToArray(Type.GetType("System.String")));
}
}
}
1) Did I successfully make AddString andToString threadsafe?
2) In the ToString method I've created is it necessary to lock there to make it threadsafe?
3) Is it only the methods that modify data that need to be locked or do both the read and write opperations need to be locked to make it threadsafe?
Thank you so much for your time!
No, you haven't made those calls thread-safe - because the _stringArrayList field is protected. Subclasses could be doing whatever they like with it while AddString and ToString are being called.
For example (as the other answers claim that your code is thread-safe.)
public class BadStringMe : StringMe
{
public void FurtleWithList()
{
while (true)
{
_stringArrayList.Add("Eek!");
_stringArrayList.Clear();
}
}
}
Then:
BadStringMe bad = new BadStringMe();
new Thread(bad.FurtleWithList).Start();
bad.AddString("This isn't thread-safe");
Prefer private fields - it makes it easier to reason about your code.
Additionally:
Prefer List<T> to ArrayList these days
You're locking with a static variable for some reason... so even if you've got several instances of StringMe, only one thread can be in AddString at a time in total
Using typeof(string) is much cleaner than Type.GetType("System.String")
3) Is it only the methods that modify data that need to be locked or do both the read and write opperations need to be locked to make it threadsafe?
All, assuming that there might be some operations. If everything is just reading, you don't need any locks - but otherwise your reading threads could read two bits of data from the data structure which have been modified in between, even if there's only one writing thread. (There are also memory model considerations to bear in mind.)
1) Did I successfully make AddString andToString threadsafe?
Yes, If you change _stringArrayList to be private
2) In the ToString method I've created is it necessary to lock there to make it threadsafe?
Yes
3) Is it only the methods that modify data that need to be locked or do both the read and write opperations need to be locked to make it threadsafe?
Read and write.
Yes to all three (i.e. read/write to the last).
But there is more:
You make your lock object static, while the data you protect is a per instance field. That means that all instances of StringMe are protected against each other, event though they have distinct data (i.e. instances of _stringArrayList). For the example you give, you can remove the static modifier from _locker. To be more precise, you typically define a "lock" for a set of data, or yet better invariants, you want to preserve. So usually, the lifetime (and scope) of the lock should equal that of the data.
Also, for good measure, you should not have a higher visibility on the data you protect than on the lock. In your example, a derived implementation could alter _stringArrayList (since it is protected) without acquiring the lock, thus breaking the invariant. I would make them both private and, if you must, only expose _stringArrayList through (properly locking) methods to derived classes.

Locking function body with function parameter object

Today I came across this piece of code
internal object UpdatePracownik(object employee)
{
lock (employee)
{
// rest of the code
}
return employee;
}
I was wondering if this is valid solution for locking access to function?
Wouldn't be better to use attribute
[MethodImpl(MethodImplOptions.Synchronized)]
instead of this kind of lock ?
Well it depends. If all threads call this method by passing the same globally visible object as parameter then they will all see the same lock and there will be no problems.
If instead each thread will call this method by passing its own object then locking is useless because they all see different locks. We must know the context in which the method is called to see if this is safe or not.
Using the synchronization method proposed by you makes the entire method body be wrapped in a lock(this) statement like:
internal object UpdatePracownik(object employee)
{
lock (this)
{
// code
}
}
which will guarantee atomicity of execution by multiple threads but may be too coarse-grain for your purposes and is generally not advisable.
Using the MethodImpl attribute to synchronise the method is equivalent to locking on an object that is specific to the method.
This means that only one thread at a time can run the method, but there might not be a need to exclude other threads as long as they don't use the same data.
It also means that the method is synchronised by itself, but you might want to lock other methods too using the same identifier. You might for example want the method DeletePracownik to be synchronised along with UpdatePracownik, so that you can't delete one object while it's being updated.
Locking on the employee instance is a bad idea, as is lock on 'this' both for the same reason: code outside of your control may also lock on those instances and cause deadlocks (blogs.msdn.com/b/bclteam/archive/2004/01/20/60719.aspx). It is preferable to use a private member:
private readonly object _lock = new object();
...
lock (_lock)
{
..
}
Furthermore you should familiarise yourself with ReaderWriterLockSlim. Often you may want to allow concurrent access to certain functions, unless a write operation is in progress:
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
public void ReadOp()
{
_rwLock.EnterReadLock(); //only blocks if write lock held
try
{
//do read op
}
finally
{
_rwLock.ExitReadLock();
}
}
public void WriteOp()
{
_rwLock.EnterWriteLock(); //blocks until no read or write locks held
try
{
//do write op
}
finally
{
_rwLock.ExitWriteLock();
}
}

Should synclock be used on properties?

I have been reading around and am getting conflicting answers on whether I should or should not use synclock on properties.
I have a multi-threaded application that needs to get/set properties across threads on instance objects. It is currently implemented without using synclock and I have not noticed any problems so far. I am using synclock on common static methods but I'd like to implement my instance classes properly and in a thread safe way.
Any feedback would be greatly appreciated.
A good rule of thumb is that you need to lock if any of the following conditions hold true:
if any field of an object is going to be modified on more than one thread
if any modifications involve accessing more than one field
if any modifiable field is a Double, Decimal, or structured value type
if any modifications involve read-modify-write (i.e. adding to a field or setting one field with the value from another)
then you probably need to lock in every method or property that accesses those fields.
EDIT: Keep in mind that locking inside of a class is rarely sufficient -- what you need to do is make sure that things don't go wrong across the span of an entire logical operation.
As #Bevan points out, if calling code needs to access an object more than once, the client code should take out its own lock on the object for the entire duration of its work to ensure that another thread doesn't get "in between" its accesses and foul up its logic.
You also need to take care that if anything needs to take out multiple locks at once, that they always be taken in the same order. If thread 1 has a lock on instance A and tries to lock instance B, and thread 2 has a lock on instance B and tries to get a lock on instance A, both threads are stuck and unable to proceed -- you have a deadlock.
You can't make an object thread safe just by surrounding individual methods with locks. All you end up doing is serialising (slowing down) access to the object.
Consider this minor example:
var myObject = ...
var myThreadSafeList = ...
if (!myThreadSafeList.Contains(myObject))
{
myThreadSafeList.Add(myObject);
}
Even if myThreadSafeList has every method locked, this isn't threadsafe because another thread can alter the contents of the list between the calls to Contains() and Add().
In the case of this list, an additional method is needed: AddIfMissing():
var myObject = ...
var myThreadSafeList = ...
myThreadSafeList.AddIfMissing(myObject);
Only by moving the logic into the object can you surround both operations with the lock and make it safe.
Without further details, it's hard to comment futher, but I'd suggest the following:
Make all properties read-only, and allow anyone to read them at any time
Provide mutator methods that take sets of properties that get modified together, and make the changes atomically within a lock
To illustrate:
public class Person {
public string FullName { get; private set; }
public string FamilyName { get; private set; }
public string KnownAs { get; private set; }
public void SetNames( string full, string family, string known) {
lock (padLock) {
...
}
}
}

How to synchronize multi-threaded calls to the same method

I have a method that is getting called from multiple threads. Each of the threads have their own instance of the class. What's the most straightforward way to synchronize access to the code?
I can't just use lock(obj) where obj is an instance member, but would it be sufficient to just declare obj as static on the class? So all calls to the method would be locking on the same object? A simple illustration follows:
class Foo
{
static object locker = new object();
public void Method()
{
lock(locker)
{
//do work
}
}
}
EDIT: The //do work bit is writing to a database. Why I need to serialize the writes would take 3 pages to explain in this particular instance, and I really don't want to relive all the specifics that lead me to this point. All I'm trying to do is make sure that each record has finished writing before writing the next one.
Why do you need any synchronization when the threads each have their own instance? Protect the resource that is shared, don't bother with unshared state. That automatically helps you find the best place for the locking object. If it is a static member that the objects have in common then you indeed need a static locking object as well.
Your example would certainly work, though there must be some resource that is being shared across the different instances of the class to make that necessary.
You left out the most important part: what data is involved in // do work
If // do work uses static data then you have the right solution.
If // do work only uses instance data then you can leave out the lock() {} altogether (because 1 instance belongs to 1 Thread) or use a non-static locker (1 instance, multiple threads).

Categories

Resources