Should synclock be used on properties? - c#

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) {
...
}
}
}

Related

Lock in multithreaded App 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.

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.

How do I control the access of multiple threads to a collection of objects?

I'm writing an application that displays a list of objects which the user can select and then view and edit the properties of through a PropertyGrid control. The object's properties are populated by time consuming process of extracting information from files through the use of a secondary thread. But I'd also like to allow the user to continue viewing other objects as the extraction process is proceeding.
After reading the responses to my previous questions on SO. It sounds like because the properties that are being written by the extraction process do not intersect the properties that are editable by the user through the property grid I shouldn't have an issue with the two threads editing the objects at the same time. Although it's possible for the user to see an incorrect value if they are incredibly unlucky and the property grid end up reading the object in the middle of a non-atomic write.
However, I'd still like to know how I might set this up to prevent the user from editing or viewing an object which is in the middle of being extracted. I'm very very new to multithreading, but most examples that I've read so for show a separate token Object being created to use to lock access to to the actual Object of interest. The answers to my other previous question confirmed that it is typical to create a separate object like this specifically for locking.
So now what I'd like to know is how is this handled in my case where I have a large collection of objects? I'd like to create locks that prevents the property grid from displaying the object a user selects if it is currently being extracted to.
Do I need to create a separate collection of lock Objects that is kept in sync with my real collection? So if an object is added or removed from my main collection I have to add or remove lock objects from my lock collection?
Do I lock to the actual objects rather then creating separate token lock objects?
What about adding a "IsBeingExtracted" Boolean property to the objects that the property grid can check to see if the object is in the middle of being written to? This would then be set at the very beginning and very end of the extraction process.
Or how about a static field somewhere that references the current (if any) object that is current being extracted to. The property grid could then check that the latest object it was ask to display was not the object referenced by this static field? This of course wouldn't work if there were multiple extraction threads.
What's the best/correct way to do this? Personally I like the boolean property option the best, but would like to know what others who actually know what they are doing think.
Couldn't you just make the collection that holds the objects a SynchronizedCollection<T>? It will make sure that only one thread can add or access objects at a time. Then, rather than worry about how to synchronize access to each object's properties, don't add the object to the collection until it has been populated.
Something like this:
private readonly ICollection<Item> Items = new SynchronizedCollection<Item>();
// Run this on the background thread.
public void PopulateItems()
{
using (var file = File.OpenRead("BigFile.txt"))
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
var item = new Item();
PopulateItem(item);
Items.Add(item);
}
}
}
public void PopulateItem(Item item)
{
// Do time-consuming work.
}
The property grid can happily do whatever it wants with the object because by the time it shows up in the list, the extraction thread is finished with it. No explicit locking required.
Make your collection of objects a Dictionary and then lock on the keys.
In general, using one or several locks depends on the degree of concurrency that you want to achieve.
The less locks you have (say, one global lock), the less concurrency there'll be because many operations can compete for the lock and prevent each other from running.
The more locks you have, the more concurrency you can achieve, but the more overhead there is in managing locks.
Using a lock that is the object being modified makes sense if what you are protecting with the lock is only this object. You'll see many examples using a separate object because you then don't need to thing about the scope of the protection.
In your specific case, I do not really understand what is being protected. Are you trying to prevent the concurrent modification of a property of an object, i.e. by the background process or the user ?
As a user cannot do more than one thing at a time, there is no need for lots of concurrency, thus there is no need to have many locks.
What you could do is have a single lock that is taken when the property grid enters editing mode and when a background process is about to set the same property being edited (otherwise, there is no need for locks).
I think the best way would be to use the ManualResetEvent object with a timeout. That way you can tell the user that it is being extracted and to try again in a few seconds.
public class Item : IDisposable // I know it is a horrible class name...
{
private readonly ManualResetEvent accessibleEvent = new ManualResetEvent(false);
public void Extract()
{
try
{
// .....
}
finally
{
accessibleEvent.Set(); // unlock
}
}
public void Edit()
{
if (!accessibleEvent.WaitOne(1000)) // wait 1 second
{
// notify user?
}
// ....
}
public void Dispose()
{
((IDisposable)accessibleEvent).Dispose();
}
}

Concurrent object locks based on ID field

I have a producer/consumer process. The consumed object has an ID property (of type integer), I want only one object with the same ID to be consumed at a time. How can I perform this ?
Maybe I can do something like this, but I don't like it (too many objects created while only one or two with the same ID a day can be consumed and the lock(_lockers) is a bit time consuming :
private readonly Dictionary<int,object> _lockers = new Dictionary<int,object>();
private object GetLocker(int id)
{
lock(_lockers)
{
if(!_lockers.ContainsKey(id))
_lockers.Add(id,new object());
return _lockers[id];
}
}
private void Consume(T notif)
{
lock(GetLocker(notif.ID))
{
...
}
}
enter code here
NB : Same question with the ID property being of type string (in that cas maybe I can lock over the string.Internal(currentObject.ID)
As indicated in comment, one approach would be to have a fixed pool of locks (say 32), and take the ID modulo 32 to determine which lock to take. This would result in some false sharing of locks. 32 is number picked from the air - it would depend on your distibution of ID values, how many consumers, etc.
Can you make your IDs to be unique for each object? If so, you could just apply a lock on the object itself.
First off,
have you profiled to establish that lock(_lockers) is indeed a bottleneck? Because if it's not broken, don't fix it.
Edit: I didn't read carefully enough, this is about the (large) number of helper objects created.
I think Damien's got a good idea for that, I'll leave this bit about the strings:
Regarding
NB : Same question with the ID
property being of type string (in that
cas maybe I can lock over the
string.Internal(currentObject.ID)
No, bad idea. You can lock on a string but then you will have to worry about wheter they may be interned. Hard to be sure they are unique.
I would consider a synced FIFO queue as a seperate class/singleton for all your produced objects - the producers enqueues the objects and the consumers dequeue - thus the actual objects do not require any synchronization anymore. The synchronisation is then done outside the actual objects.
How about assigning IDs from a pool of ID objects and locking on these?
When you create your item:
var item = CreateItem();
ID id = IDPool.Instance.Get(id);
//assign id to object
item.ID = id;
the ID pool creates and maintains shared ID instances:
class IDPool
{
private Dictionary<int, ID> ids = new Dictionary<int, ID>();
public ID Get(int id)
{
//get ID from the shared pool or create new instance in the pool.
//always returns same ID instance for given integer
}
}
you then lock on ID which is now a reference in your Consume method:
private void Consume(T notif)
{
lock(notif.ID)
{
...
}
}
This is not the optimal solution and only offsets the problem to a different place - but if you believe that you have pressure on the lock you may get a performance improvement using this approach (given that e.g. you objects are created on a single thread, you do not need to synchronize the ID pool then).
See How to: Synchronize a Producer and a Consumer Thread (C# Programming Guide)
In addition to simply preventing
simultaneous access with the lock
keyword, further synchronization is
provided by two event objects. One is
used to signal the worker threads to
terminate, and the other is used by
the producer thread to signal to the
consumer thread when a new item has
been added to the queue. These two
event objects are encapsulated in a
class called SyncEvents. This allows
the events to be passed to the objects
that represent the consumer and
producer threads easily.
--Edit--
A simple code snippet that I wrote sometime back; see if this helps. I think this is what weismat is pointing towards?
--Edit--
How about following:
Create an object, say CCustomer that would hold:
An object of type object
And a bool - for instance, bool bInProgress
Dictionary that would hold
now when you check following
if(!_lockers.ContainsKey(id))
_lockers.Add(id,new CCustomer(/**bInProgress=true**/));
return _lockers[id]; **//here you can check the bInProgress value and respond accordingly**.

Categories

Resources