Locking function body with function parameter object - c#

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();
}
}

Related

Multithreading and Locking (Thread-Safe operations)

So I have a class with a few methods which all use locking in order to prevent weird things happening when someone uses an instance of my class with multiple threads accessing it:
public class SomeRandomClass
{
private object locker = new object();
public void MethodA()
{
lock (locker)
{
// Does something
MethodB();
}
}
public void MethodB()
{
lock (locker)
{
// Does something else
}
}
}
As we can see, MethodB() is automatically accessed by MethodA(), but that won't work since MethodA() has currently locked the locker object.
I want to make MethodB() accessible publicly, so you can call it manually whenever needed, but I do NOT want it to be used while MethodA() is doing things (that's why I'm using a locker object).
And of course I do not want MethodA() to do things while MethodB() is doing stuff. I basically want only one of all the methods to be used at the same time, but MethodA() needs to access MethodB() somehow without removing the lock (so that it stays completely thread-safe the whole time).
I really hope it is kind of understandable what I'm trying to ask... If there's any questions about my question, then please go ahead and post them below. Answers/Solutions are very much appreciated as well!
The solution is probably incredibly easy and I'm just not seeing it.
By the way, the above is supposed to be C#-code.
An easy solution would be to create a private method that contains what MethodB does that can be called by MethodA and another public MethodB
The private MethodB does not lock, only the public ones do.
For example:
public class SomeRandomClass {
private object locker = new object();
public void MethodA {
lock(locker) {
// exclusive club
// do something before calling _methodB
_methodB();
}
}
private void _methodB {
// do that, what used to be done by MethodB
}
public void MethodB {
//this one only exists to expose _methodB in a thread-safe context
lock(locker) {
_methodB();
}
}
}
P.S.
I think it is obvious to you and everyone else why your code is somewhat designed to create a deadlock.
Update:
Apparently lock(object) {} is re-entrant as pointed out in the comments, so the obvious deadlock isn't even one.
Locking forbids what you're trying to do -- that's its purpose.
One thing to do here is creating a private method that you can access from both methodA and methodB. That method wouldn't use locking, and wouldn't be thread safe, but could be called from either one of the locking methods.
You have race condition here: it make data incorrect. I suppose method A write static theVar variable of type string:
thread A -> call method A -> lock -> change theVar to "A"
thread B -> call method B -> wait because thread A keep lock
thread A -> release lock to call method B
The bug here: thread B process theVar of "A"
If method B only read theVar, it's Ok.
Your lock mechanism needs to allow locks to be taken in a recursive way (by the same thread only), usually called reentrant. lock (Monitor class internally).
It is legal for the same thread to invoke Enter more than once without it blocking; however, an equal number of Exit calls must be invoked before other threads waiting on the object will unblock.
See also Recursive / nested locking in C# with the lock statement
and Re-entrant locks in C#
As pointed out by Henk Holterman in the comment, the Monitor class is already reentrant. And the lock statement is managing the right amount of Enter and Exit calls to the underlying Monitor class.
The ReaderWriterLockSlim class is an example for a lock mechanism where one can choose between reentrant and non-reentrant. See https://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx
var rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
Replace your lock { ... } with
ReaderWriterLockSlim rwLock =
new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
...
try
{
rwLock.EnterWriteLock();
// Does something
}
finally
{
rwLock.ExitWriteLock();
}
```
The Code written by you is correct.
Because according to Microsoft, once the call is acquired even if program calls for lock in the same flow, it will not be blocked as lock is already with the thread.
The code works as below.
call "MethodA" -->acquire lock --> call "MethodB" (will not be blocked as thread is already acquired lock) and execution will be completed.
Call "MethodB" in between previous execution from another thread, the execution will be blocked as lock is with first thread.

When and how to use lock()?

I'm currently working on a multithreaded project. Mainly for learning purposes.
My part in this project is to write a server application.
But I got to a point where this whole locking of variables is a bit confusing because I don't know exactly how it works and when/where I have to use it.
Lets say I have a class ClientHandler that contains a List<Client> clientList.
ClientHandler has a property ClientList that returns clientList:
private List<Client> clientList;
public List<Client> ClientList
{
get { lock (lockObject) return clientList; }
set { lock (lockObject) clientList = value; }
}
NetworkHandler runs a second Thread that works with this List<>.
In this network Thread the retrieved List<> is locked with another object while in use.
My question is how this locking works.
If I lock this List<> in the network Thread (with a different object than ClientHandler) is it thread-safe? So in general is it true that if you lock a variable with whatever object, is it locked for everyone else trying to access it?
I just want to be sure that the List<> cannot be altered while it is processed in another Thread.
I am assuming that you want the List itself to be passed around and manipulated on separate threads via Add/Remove/Clear/foreach methods, but not the objects themselves.
If this is the case then the List itself needs to implement an internal locking mechanism on each operation (Add, Remove, etc). The List creates the lockObject, not you.
Obviously a List<T> can't do this, so you need to either derive from it or implement your own IList/ICollection class, or you can just use a collection from the System.Collections.Concurrent namespace which is designed for this purpose already, such as ConcurrentDictionary.
If you want to make the objects inside the collection accessible by multiple threads then you have to make those objects thread safe... which is a completely separate step.
For a brief explanation of how the lock keyword works:
When you lock an object by specifying lock (someObject) { }, everything inside the code block will only be executed when every other instance of a lock on that same object is not executing.
At the start of the lock code block it sets a thread-safe flag somewhere that says "I'm reserving this object", and at the end of the lock block it says "I am no longer reserving this object." At the start of the lock block if it tries to lock an object but that object is already locked then it will wait indefinitely until it can successfully obtain a lock, blocking the calling thread in the process.
In your example you are using an inline code block:
get { lock (lockObject) return clientList; }
Which is equivalent to:
get
{
lock (lockObject)
{ // Lock starts here
return clientList;
} // Lock ends here
}
So if you access that property then the object is unlocked as soon as its given to the caller of the property. Then the caller can go ahead and call the Add() method on that List and internally it will access the inner collection with no locking mechanism, so it won't be thread safe.
Instead, the List needs to call lock everytime it accesses the internal fields, such as the _innerList field, like so:
public void Add(object item)
{
lock (_innerList)
{
_innerList.Add(item);
}
}

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.

prevent method from executing from different threads at the same time

Am I correct that the only way to prevent a method from being executed twice at the same time is by using a lock statement?
private object lockMethod = new object();
public void Method() {
lock (lockMethod) {
// work
}
}
public void FromThread1() {
Method();
}
public void FromThread2() {
Method();
}
Of course I can also use MethodImpl(MethodImplOptions.Synchronized) what would be almost the same.
Are there other techniques?
Am I correct that the only method to prevent method to execute twice at the same time is using lock statement?
No, but this is the "standard" way, and probably the best. That being said, typically you'd use a lock to synchronize access to specific data, not to a method as a whole. Locking an entire method will likely cause more blocking than necessary.
As for other methods, the System.Threading namespace contains many other types used for synchronization in various forms, including ReaderWriterLockSlim, Semaphore, Mutex, the Monitor class (which is what lock uses internally), etc. All provide various ways to synchronize data, though each is geared for a different scenario. In this case, lock is the appropriate method to use.

multithreading: lock on property - is this correct?

I have written the following code:
static readonly object failedTestLock = new object();
public static Dictionary<string, Exception> FailedTests
{
get
{
lock (failedTestLock)
{
return _failedTests;
}
}
set
{
lock (failedTestLock)
{
_failedTests = value;
}
}
}
public void RunTest(string testName)
{
try
{
//Run a test
}
catch (Exception exception)
{
// ?? Is this correct / threadsafe?
FailedTests.Add(testName, exception);
}
}
QUESTION:
Is this a correct manner to safely add the failed test to the Dictionary?
Is this threadsafe?
Is FailedTests.Add called INSIDE the lock or OUTSIDE the lock?
Can you explain why this is correct/threadsafe or why not?
Thanks in advance
The fundamental problem with the code above is that it only locks access to _failedTests when a thread is getting the dictionary or setting it. Only one thread can get a reference to the dictionary at a time, but once a thread has a reference to the dictionary, it can read and manipulate it without being constrained by locks.
Is this a correct manner to safely add
the failed test to the Dictionary?
No, not if two threads are trying to add to the dictionary at the same time. Nor if you expect reads and writes to happen in a particular order.
Is this threadsafe?
It depends what you mean by threadsafe, but no, not by any reasonable definition.
Is FailedTests.Add called INSIDE the
lock or OUTSIDE the lock?
The dictionary retrieval (the get accessor) happens inside a lock. This code calls Add after releasing the lock.
Can you explain why this is correct/threadsafe or why not?
If multiple threads operate on your dictionary at the same time, you can't predict the order in which those threads will change its contents and you can't control when reads will occur.
This is not thread-safe access to a dictionary, because only the property access that returns the dictionary object is thread-safe, but you are not synchronizing the call to the Add method. Consider using ConcurrentDictionary<string,Exception> in this case, or synchronize calls to Add manually.
I don;t thinks this is threadsafe, because the lock is kept only in the very brief moment where the pointer to the collection is returned. When you Add to the collection there is no lock so if two threads try to add at the same time you'll get a nasty error.
So you should lock around the FailedTest.Add code.
You may also want to look into concurrent collections, they might provide what you need.
Regards GJ
The call to Add() is outside the locks.
You can solve it by writing your own Add() method to replace the property.

Categories

Resources