In an application that I am developing I will be using 2 threads to do various operations. (I will not go into detail here.) These threads work in loops, checking if there is work to be done, doing work, calculating the time they need to wait and waiting. (See below)
public Global : System.Web.HttpApplication
{
private static Thread StartingDateThread;
private static Thread DeadlineDateThread;
private static object o1;
private static object o2;
public static Thread GetStartingDateThreadInstance
{
get
{
if(StartingDateThread==null)
{
StartingDateThread=new Thread(new ThreadStart(MonitorStartingDates));
}
return StartingDateThread;
}
}
public static Thread GetDeadlineThreadInstance
{
get
{
if(DeadlineDateThread==null)
{
DeadlineDateThread=new Thread(new ThreadStart(MonitorDeadlines));
}
return DeadlineDateThread;
}
}
public static object GetFirstObjectInstance
{
get
{
if(o1==null)
{
o1=new object();
}
return o1;
}
}
public static object GetSecondObjectInstance
{
get
{
if(o2==null)
{
o2=new object();
}
return o2;
}
}
protected void Application_Start(object sender, EventArgs e)
{
GetStartingDateThreadInstance.Start();
GetDeadlineThreadInstance.Start();
//////////////////////
////Do other stuff.
}
public void MonitorStartingDates()
{
while(true)
{
//Check if there is stuff to do.
//Do stuff if available.
//Check if there will be stuff to do in the future and if there is, check
//the time to wake up.
//If there is nothing to do, sleep for a pre-determined 12 hours.
if(StuffToDoInFuture)
{
Monitor.Enter(GetFirstObjectInstance);
Monitor.Wait(WaitingTime);
Monitor.Exit(GetFirstObjectInstance);
}
else
{
Monitor.Enter(GetFirstObjectInstance);
Monitor.Wait(new TimeSpan(12, 0, 0));
Monitor.Exit(GetFirstObjectInstance);
}
}
}
public void MonitorDeadlines()
{
while(true)
{
//Check if there is stuff to do.
//Do stuff if available.
//Check if there will be stuff to do in the future and if there is, check
//the time to wake up.
//If there is nothing to do, sleep for a pre-determined 3 days and 12 hours.
if(StuffToDoInFuture)
{
Monitor.Enter(GetSecondObjectInstance);
Monitor.Wait(WaitingTime);
Monitor.Exit(GetSecondObjectInstance);
}
else
{
Monitor.Enter(GetSecondObjectInstance);
Monitor.Wait(new TimeSpan(3, 12, 0, 0));
Monitor.Exit(GetSecondObjectInstance);
}
}
}
As you can see these two threads are started in the Application_Start method in the asax file. They operate if there is stuff available to do and then they calculate the time period they need to wait and then they wait. However, as users of the web application do operations new records will be inserted into the database and there will be circumstances where any of the two threads will have to resume operation sooner than planned. So, say I have a method in my DataAccess class which inserts into the database new data. (See below)
public class DataAccess
{
///////////////
//
public void InsertNewAuction()
{
///Insert new row calculate the time
Monitor.Pulse(Global.GetFirstObjectInstance);
Monitor.Pulse(Global.GetSecondObjectInstance);
///
}
}
It seems like this is an invalid operation, because at the stage where the Monitor.Pulse is called from the InsertNewAuction method I get an exception. Something like "Object synchronization method was called from an unsynchronized block of code." Is there any way of doing this? Thanks for your help
As to the specific error you're seeing, this is because Monitor.Pulse must be called inside the Monitor lock, like this (I've used lock rather than Enter/Exit, as it's safer for making sure the lock is always released, since it uses a proper try/finally block):
lock (Global.GetFirstObjectInstance)
{
Monitor.Pulse(Global.GetFirstObjectInstance);
}
In regard to the more general design question here, it's often dangerous to expose lock objects as public (or even worse, global) fields. In particular, it can be a recipe for deadlocks when multiple global locks are exposed and acquired in differing orders or when you have cases like blocking dispatches to the UI thread while holding a lock. Consider looking into alternate ways to accomplish what you're after.
As noted in the other answer, you have to acquire the lock before you can call Monitor.Pulse() on the monitor object.
That said, your code has at least one other serious bug: you are not initializing the synchronization object in a thread-safe way, which could easily lead to two different threads using two different object instances, resulting in no synchronization between those threads:
public static object GetFirstObjectInstance
{
get
{
if(o1==null)
{
o1=new object();
}
return o1;
}
}
If two threads call this getter simultaneously, they each may see o1 as null and try to initialize it. Then each might return a different value for the object instance.
You should simply initialize the object in a initializer:
private static readonly object o1 = new object();
And then return it from the getter:
public static object GetFirstObjectInstance { get { return o1; } }
That addresses the thread-safety issue. But you still have other issues with the code. First, you should encapsulate synchronization in an object, not expose the actual synchronization object instance. Second, assuming you are going to expose the synchronization object, I don't understand why you bother with the property, since you made the field public. The field should be private if you want to use a property as well.
It would also be better if the property followed normal .NET naming conventions. A method that returned the object would have "Get" in the name, but a property would not. Just name it "FirstObjectInstance".
Also as noted by Dan, use lock everywhere you want to acquire the lock.
There may be other issues in the code as well...I didn't do a thorough review. But the above you need to fix for sure.
Related
I have an IDisposable object that can be accessed between multiple threads. I am trying to figure out a way to track that the object is "in use" before performing any clean up. In other words, I need to keep some sort of reference count to indicate that there are running methods (which are decremented when they complete) so that the Dispose method wouldn't continue until they are all complete (or after some timeout has passed). But I also need to make sure that once Dispose has been entered that any future calls to Method fail.
Something like:
class MyObject : IDisposable
{
private long _counter;
private bool _stopping;
private IDisposable _someResource;
public void Method()
{
if (_stopping)
throw new InvalidOperationException();
Interlocked.Increment(ref _counter);
try
{
// do some work
}
finally
{
Interlocked.Decrement(ref _counter);
}
}
public void Dispose()
{
var timeout = DateTime.Now.Add(TimeSpan.FromSeconds(15));
while ( DateTime.Now < timeout && Volatile.Read(ref _counter) > 0)
{
// wait
// Thread.Sleep(10) or something
}
_stopping = true;
//perform clean up
_someResource.Dispose();
}
}
However this won't work because Method() may be called again and _stopping hasn't been set but the Dispose would continue, invalidating everything else.
Is there a specific pattern that I can use here or perhaps some framework classes that can be used to solve this? Basically some two-way signal telling Dispose that nothing is in process so its good-to-go while signalling Method that it should fail.
I found CountdownEvent but I'm not sure how I can use it here. This answer shows an example CountdownLatch but it doesn't prevent new work from being requested.
No. Just say no to the Dispose method being responsible for "tracking" all instances consuming the class. The consumers of the class need to handle their clean-up and properly dispose.
If Dispose can be called multiple times by multiple classes, then you've just found a code smell. Only one class should being calling the dispose method; and that class should be tracking the consumers of the class with the Dispose method.
A common pattern for preventing dispose from being called multiple times is to set up a flag, similar to what you have now. Use the ObjectDisposedException as needed:
private bool _zombified;
public void Method()
{
if (_zombified)
throw new ObjectDisposedException();
// method's logic
}
public void Dispose
{
if(_zombified)
{
return;
}
_zombified = true;
// perform clean-up
}
I have two classes A & B. Both are calling each other and having their own locks. I am getting a deadlock in one particular scenario. Here is the sample code.
class A : Interface1, Interface2
{
private B _bInstance = new B();
private object _aSync = new object();
private static A Instance;
private A(){}
public GetInstance()
{
if (Instance == null) Instance = new A();
return Instance;
}
void Method1()
{
lock(_aSync)
{
_bInstance.Method1();
}
}
void WriteData()
{
lock (_aSync)
{
WriteToFile();
}
}
}
class B
{
private object _bSync = new object();
void Method1()
{
lock (_bSync)
{
// Have some code here which need to protect my
// member variables.
A.GetInstance.WriteData();
}
}
void OneSecondTimerEvent()
{
lock (_bSync)
{
// Have some code here which need to protect my
// member variables.
A.GetInstance.WriteData();
}
}
}
How do I synchronize the OneSecondTimerEvent(), if One second timer gets triggered When the A.Method1() is being executed?
Yes, your code shows canonical example of deadlock - 2 resources waiting for each other to continue.
To resolve you can:
manually order lock statements (i.e. B never takes additional locks if A already have lock),
scope locks to only internal state of each class and never nest locks. In this case sometimes you'd need to copy state to call external methods.
use other synchronization primitives/constructs that allow such nesting (i.e. Reader-Writer locks).
Rather than try and solve this particular deadlock issue (which btw, is a classic result of locking things in an inconsistent order), I would strongly advise designing a better relationship between A and B. The fact you had to use a static instance to achieve a circular dependency should be a big clue you've done something wrong. Perhaps A and B should reference a 3rd class C, which is solely responsible for locking and writing the data? (Although it's difficult to say without a bit more context).
Why is it a bad practice to use lock as in the following code, I'm assuming this is a bad practice based on the answers in this SO question here
private void DoSomethingUseLess()
{
List<IProduct> otherProductList = new List<IProduct>();
Parallel.ForEach(myOriginalProductList, product =>
{
//Some code here removed for brevity
//Some more code here :)
lock (otherProductList)
{
otherProductList.Add((IProduct)product.Clone());
}
});
}
The answers over there mentions that it is bad practice , but they don't say why
Note: Please ignore the usefulness of the code, this is just for example purpose and i know it is not at all useful
From the C# language reference here:
In general, avoid locking on a public type, or instances beyond your code's control. The common constructs lock (this), lock (typeof (MyType)), and lock ("myLock") violate this guideline:
lock (this) is a problem if the instance can be accessed publicly.
lock (typeof (MyType)) is a problem if MyType is publicly accessible.
lock("myLock") is a problem because any other code in the process
using the same string, will share the same lock.
Best practice is to define a private object to lock on, or a private
static object variable to protect data common to all instances.
In your case, I would read the above guidance as suggesting that locking on the collection you will be modifying is bad practise. For example, if you wrote this code:
lock (otherProductList)
{
otherProductList = new List<IProduct>();
}
...then your lock will be worthless. For these reasons it's recommended to use a dedicated object variable for locking.
Note that this doesn't mean your application will break if you use the code you posted. "Best practices" are usually defined to provide easily-repeated patterns that are more technically resilient. That is, if you follow best practice and have a dedicated "lock object," you are highly unlikely to ever write broken lock-based code; if you don't follow best practice then, maybe one time in a hundred, you'll get bitten by an easily-avoided problem.
Additionally (and more generally), code written using best practices is typically more easily modified, because you can be less wary of unexpected side-effects.
It might be not a good idea indeed, because if someone else uses the same object reference to do a lock, you could have a deadlock. If there is a chance your locked object is accessible outside your own code, then someone else could break your code.
Imagine the following example based on your code:
namespace ClassLibrary1
{
public class Foo : IProduct
{
}
public interface IProduct
{
}
public class MyClass
{
public List<IProduct> myOriginalProductList = new List<IProduct> { new Foo(), new Foo() };
public void Test(Action<IEnumerable<IProduct>> handler)
{
List<IProduct> otherProductList = new List<IProduct> { new Foo(), new Foo() };
Parallel.ForEach(myOriginalProductList, product =>
{
lock (otherProductList)
{
if (handler != null)
{
handler(otherProductList);
}
otherProductList.Add(product);
}
});
}
}
}
Now you compile your library, send it to a customer, and this customer writes in his code:
public class Program
{
private static void Main(string[] args)
{
new MyClass().Test(z => SomeMethod(z));
}
private static void SomeMethod(IEnumerable<IProduct> myReference)
{
Parallel.ForEach(myReference, item =>
{
lock (myReference)
{
// Some stuff here
}
});
}
}
Then there could be a nice hard-to-debug deadlock for your customer, each of two used thread waiting for the otherProductList instance to be not locked anymore.
I agree, this scenario is unlikely to happen, but it illustrates that if your locked reference is visible in a piece of code you do not own, by any possible way, then there's a possibility for the final code to be broken.
This question already has answers here:
how to obtain a lock in two places but release on one place?
(4 answers)
Closed 8 years ago.
I want to reask my previous question how to obtain a lock in two places but release on one place? because it seems too old and noone sees my updated code.
The question is - is my code correct and how to fix it if not?
I've tried similar code in the application and it hangs, but I don't now why, so I guess probably my code still wrong...
public void obtainLock() {
if (needCallMonitorExit == false) {
Monitor.Enter(lockObj);
needCallMonitorExit = true;
}
// doStuff
}
public void obtainReleaseLock() {
try {
lock (lockObj) {
// doAnotherStuff
}
} finally {
if (needCallMonitorExit == true) {
needCallMonitorExit = false;
Monitor.Exit(lockObj);
}
}
}
One of my methods should obtain the lock. another method should obtain the same lock and release it. sometimes just obtainReleaseLock is called. sometimes obtainLock is called (probably several times) and after a while obtainReleaseLock is called. These two methods are always called from the same thread, however lockObj is used in another thread for synchronization.
If you really need to go this way and don't want to use the alternatives provided by Marc, at least, put it into its own class:
public class LockObject
{
object _syncRoot = new object();
object _internalSyncRoot = new object();
public LockToken Lock()
{
lock(_internalSyncRoot)
{
if(!_hasLock)
{
Monitor.Enter(_syncRoot);
_hasLock = true;
}
return new LockToken(this);
}
}
public void Release()
{
lock(_internalSyncRoot)
{
if(!_hasLock)
return;
Monitor.Exit(_syncRoot);
_hasLock = false;
}
}
}
public class LockToken : IDisposable
{
LockObject _lockObject;
public LockToken(LockObject lockObject) { _lockObject = lockObject; }
public void Dispose() { _lockObject.Release(); }
}
This would allow you to use it like this:
LockObject _lockObj = new LockObject();
public void obtainLock()
{
_lockObj.Lock();
// doStuff
}
public void obtainReleaseLock()
{
using(_lockObj.Lock())
{
// doAnotherStuff
}
}
One word of caution:
If your thread is aborted after the call to obtainLock and before the call to obtainReleaseLock, your program will deadlock.
If you use Monitor.Enter you will need to call exactly that many Monitor.Exit calls on the same object, on the same thread. By using a lock block this is automatically done for you - as soon as you are outside the scope of the lock block, the lock count is decreased. Within the same thread it is perfectly legal to lock multiple times on the same object (via both mechanisms).
Keeping that in mind, maintaining your own "lock state" variable would only make things more complex. What if two threads access the needCallMonitorExit variable at the same time?
If I were you I would stick to lock blocks, and re-order code to fit inside them. Put as little code inside the blocks as possible.
Is the snippet below "safe" for performing some initialization once in a multithreaded program?
I'm a bit worried that boxing/unboxing might cause some problem...
private static object initialized = false;
public static void Initialize()
{
lock (initialized)
{
if ((bool)initialized == false)
{
DoInitialization();
initialized = true;
}
}
}
Note that I can't just do the initialization from Main or some other single threaded context.
You are right - that's not going to work because you are reassigning the object you are locking on.
You can do this with two seperate members - an object to lock on that is assigned only once, and then a boolean that you can read or assign to (after you have locked).
You may also want to consider if a singleton would be appropriate here.
Try a double-checked locking.
private static volatile bool initialized = false;
private static object syncObject = new object();
public static void Initialize() {
if (!initialized) {
lock (syncObject) {
if (!initialized) {
DoInitialization();
initialized = true;
}
}
}
}
A few options:
lock on a once-assigned reference-type, as Mark has mentioned.
Initialize on the static-constructor, which is guaranteed to only run once. Con: Hard to control when you want the initialization to occur.
If possible, the Lazy class, which is thread-safe.
All 3 methods can also be used to create Singletons.