I see locking using static readonly objects alot, what is the significance of this statement in the below given code?I know lock is applied on an object , is this just an object for making locks work, is it just a hack , because i don't need any object here but just creating an object in order to make locking work?
Also instead of just saying object obj1= new object() i use readonly and static, i guess due to increasing performance but how readonly and static helps increasing performance?
static readonly object locker = new object();
Code is as follows:
class ThreadSafe
{
static bool done;
static readonly object locker = new object();
static void Main()
{
new Thread (Go).Start();
Go();
}
static void Go()
{
lock (locker)
{
if (!done) { Console.WriteLine ("Done"); done = true; }
}
}
}
It is a recommended practice to lock using separate private objects as opposed to already existing globally visible objects because there is a lower risk of other code's locking decisions to interfere with your private locking scheme (this kind of issues is extremely difficult to document against, and to diagnose; so it's best to make them impossible).
That locker object needs to be static, if it serves a static class, or if your intention is application wide locking; and it needs to be an instance object if it serves to lock only a single object instance, allowing concurrent processing of other objects of the same served class or class hierarchy.
Explicit read-onliness does not have a direct impact on performance in this particular case, but it does in most others (mainly by preventing reloads) and so it is a useful habit to label all read-only objects as such.
Having an object whose sole purpose is to provide a lock simplifies things a bit. In order to keep outside code from messing with your locks and causing you all kinds of grief, you really really want a lock that's solely visible to you. Easiest way to accomplish that, would be to create an object. (If you have another object that no one else will have access to, you could conceivably use that...but having the lock separate from everything else tends to keep stuff conceptually simpler.)
As for why it's static...that's not so much a performance thing as a correctness one. In order to lock in a static method or synchronize access to a static resource, you need an object that belongs to the class, not to an instance. Otherwise, every instance would be locking its own lock rather than sharing one -- which would be pretty useless unless there was only ever one instance, and incorrect even then. For a non-static method, you wouldn't use static unless for some reason you were accessing static properties or something like that. If you did use it, and didn't need to synchronize access between instances, you'd end up locking unnecessarily and slowing stuff down.
Related
This question already has answers here:
C# lock statement, what object to lock on?
(4 answers)
Closed 6 years ago.
As far as I've understood from colleagues and the web, it is bad practice to lock on the object that is being synchronized, but what I dont understand is why?
The following class is supposed to load settings to a dictionary, and it has a method to retrieve settings as well.
public class TingbogSettingService : ITingbogSettingService
{
private readonly ISettingRepository _settingRepository;
private readonly ICentralLog _centralLog;
private Dictionary<string, ISetting> _settingDictionary = new Dictionary<string, ISetting>();
public TingbogSettingService(ISettingRepository settingRepository, ICentralLog centralLog)
{
_settingRepository = settingRepository;
_centralLog = centralLog;
}
public ISetting GetSetting(string settingName)
{
ISetting setting;
if (!_settingDictionary.TryGetValue(settingName, out setting))
{
return null;
}
return setting;
}
public void LoadSettings()
{
var settings = _settingRepository.LoadSettings();
try
{
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
}
catch (Exception ex)
{
_centralLog.Log(Targets.Database, LogType.Error, $"LoadSettings error: Could not load the settings", new List<Exception>() { ex });
}
}
}
During the LoadSettings function I want to lock the _settingDictionary, so that GetSetting will be blocked, until the new settings are loaded.
Should I use a dedicated lock object instead?
For instance:
private static readonly object m_Lock = new object();
…
lock (m_Lock)
EDIT
I thought that lock(_settingDictionary) would lock the _settingDictionary itself, however I now realize that his is not the case. What I wanted was to prevent other threads from accessing _settingDictionary until the new settings were loaded (LoadSettings method completed). As only 1 thread is updating the _settingDictionary, I guess I dont need a lock there at all.
As for closing the question - something similar has been asked before, yes, but the scenario is not the same. I learned from your answers and it is going to be hard to pick a winner amongst y'all.
This is quite a broad subject, but let me focus on one major problem in your code: _settingDictionary changes.
You don't lock on the field, you lock on the instance. This means that when you lock on _settingDictionary, and then you change _settingDictionary, you're not preventing any concurrent access - anyone can lock on the new _settingDictionary.
lock doesn't prevent access to the object you're locking either. If you need synchronization, you must synchronize all access to the object, including your _settingDictionary.TryGetValue. Dictionary isn't thread-safe.
The main guide-lines to what you should lock on are something like this:
The lock object is private to the locker - if it's not private, some other class might be holding a lock on your object, which may lead to deadlocks.
The field should be readonly - this is not a strict requirement, but it makes things easier. The main point is that you must not lock on an object that might change while the lock is being held; others trying to take the lock concurrently will succeed.
The lock object is a reference type - this kind of goes without saying, but you cannot lock on e.g. an int field, since it is boxed when you try to lock it - in effect, this is the same as the previous point - everyone locks on their own instance of the object, eliminating all synchronization.
Obligatory disclaimer: Multi-threading is hard. Seriously hard. Make sure you understand what's happening and what can possibly happen. Any multi-threaded code you write must be written in a way that's correct, first and foremost. http://www.albahari.com/threading/ is a great starter on all things multi-threaded in C#/.NET.
There is no "right" or "wrong" answer to this but there are some guidelines and some things to be aware of.
First, there's many that feel that Microsoft should never have allowed to lock on arbitrary objects. Instead they should've encapsulated the locking functionality into a specific class and avoided potential overhead in every other object out there.
The biggest problem with allowing locking on arbitrary objects is that if you lock on an object you make publicly available to 3rd party code, you have no control over who else might be locking on the same object. You could write your code to the letter, dotting every I and it would still end up deadlocking because some other, 3rd party, code is locking on the same object out of your control.
So that point alone is guideline enough to say "don't ever lock on objects you make publicly available".
But what if the object you want to synchronize access to is private? Well, then it becomes more fuzzy. Presumably you have full control over the code you write yourself and thus if you then lock on the dictionary, as an example, then it will work just fine.
Still, my advice would be to always set up a separate object to lock on, get into this habit, and then you won't so easily make mistakes if you later decides to expose a previously private object into the public and forgetting to separate the locking semantics from it.
The simplest locking object is just that, an object:
private readonly object _SomethingSomethingLock = new object();
Also know, though I think you already do, that locking on an object does not "lock the object". Any other piece of code that doesn't bother with locks can still access the object just fine.
Here is also something I just noticed about your code.
When you do this:
lock (x)
You don't lock on x, you lock on the object that x refers to at the time of the lock.
This is important when looking at this code:
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
Here you have two objects in play:
The dictionary that settingDictionary refers to at the time of lock (_settingDictionary)
The new dictionary that .ToDictionary(...) returns
You have a lock on the first object, but not on the second. This is another scenario where having a dedicated locking object would not only make sense, but also be correct, as the above code is buggy in my opinion.
The problem you are talking about happens when you lock on an object to which external users of your class have access - most commonly, the object itself, i.e. lock (this).
If your code were locking on this instead of _settingDictionary, someone else could deadlock your code as follows:
TingbogSettingService svc = ...
lock (svc) {
Task.Run(() => {
svc.LoadSettings();
});
}
When you lock on a private object, such as _settingDictionary in your case, there harmful effect described above is avoided, because nobody outside your code can lock on the same object.
Note: Using the lock in your code does not make it thread-safe, because GetSetting method does not lock on _settingDictionary when reading from it. Moreover, the fact that you re-assing _settingDictionary inside the lock makes locking irrelevant, because after the reassignment another thread can enter protected section in the lock.
There are different thing you could lock:
a dedicated non static object: private readonly object m_Lock = new object();
a dedicated static object (your example): private static readonly object m_Lock = new object();
the object itself: lock (_settingDictionary)
this, typeof(MyClass)...
The first two are OK but actually different. Locking on a static object means the lock is shared between all instances of your classes. Locking on a non-static object means the lock is different for each instance of your class.
The third option is OK, it's the same as the first one. The only difference is that the object is not read-only (using a read-only field is slightly better as you ensure it won't ever change).
The last option is a bad option for various reasons, see Why is lock(this) {...} bad?
So be careful about what you lock, your example uses a static object while your initial code uses a non-static object. Those are really different use cases.
It is better to use a dedicated object that is not modified by the block of code or used for other purposes in some other methods. That way the object has a single responsibility so that you don't mix the usage of it as a synchronization object, with it being maybe set to null at some point or reinitialized by another method.
lock (_settingDictionary) doesn't lock the dictionary specified between (), it locks the next block of code by using _settingDictionary as a synchronization object (To know if the block has been entered of left by another thread by setting some flags on that object).
I have a singleton below. I have multiple threads using the lookup to check if values are valid. It's been awhile since I've done anything with shared memory, so I want to make sure what locks are necessary. I'm unsure if I need a concurrent set instead of HashSet since I'm only inserting values once.
I have [MethodImpl(MethodImplOptions.Synchronized)] on the Instance property because I read that properties aren't sycrhonized (makes sense). This should prevent multiple instances being created, although I'm not sure if I should really worry about that (just extra cost of reloading the set?).
Should I make the FipsIsValid function Syncrhonized, or use some sort of concurrent set? Or are neither necessary?
public class FipsLookup
{
private static FipsLookup instance;
private HashSet<string> fips;
private FipsLookup()
{
using (HarMoneyDB db = new HarMoneyDB())
{
instance.fips = new HashSet<string>(db.Counties.Select(c => c.FIPS).ToArray());
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static FipsLookup Instance
{
get
{
if (instance == null)
{
instance = new FipsLookup();
}
return instance;
}
}
public static bool FipsIsValid(string fips)
{
var instance = FipsLookup.Instance;
return instance.fips.Contains(fips);
}
}
Should I make the FipsIsValid function Syncrhonized, or use some sort
of concurrent set? Or are neither necessary?
I think the key to this answer is the fact that you are only performing lookups on the HashSet, and not mutating it. Since it is initialized once, and only once, there is no need to synchronize the lookup.
If you do decide that along the way that you do need to mutate it, then using a proper lock or a concurrent collection would be needed.
On a side note, you can simplify your singleton by initializing the instance field once inside a static constructor:
private static FipsLookup instance;
static FipsLookup()
{
instance = new FipsLookup();
}
And now you can make Instance return the field, with no need to use [MethodImpl(MethodImplOptions.Synchronized)]:
public static FipsLookup Instance
{
get
{
return instance;
}
}
This is safe because Instance is synchronized which is equivalent to a lock. All writes happen under that lock. Releasing the lock flushes all writes (a release barrier).
Also, all read first go through the lock. It is not possible to observe a partially written hashset. A previous version of this answer made the following incorrect claims:
This is not strictly safe (under ECMA) because readers might see a half-written HashSet. In practice it is safe (on the Microsoft CLR because all stores are releases) but I wouldn't use it because there is no reason to.
When writing this I did not notice the MethodImplOptions.Synchronized. So for your entertainment this is what happens when you forget a lock.
Probably, you should be using Lazy<T> which handles this for you and it gives you lock-free reads.
MethodImplOptions.Synchronized on static members is a little evil because it locks on the type object of the class. Let's hope nobody else is locking on this (shared) object. I would fail this in a code review, mostly because there is no reason to introduce this code smell.
HashSet class is not thread safe and there is no garantee that you can access it from multiple threads and all will be ok. I'd prefer to use ConcurrentDictionary instead.
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.
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.
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).