I have a number of worker threads that call a common function. I use a lock object as follows:
static object var mylock = new object();
public void myFunction()
{
if (Monitor.TryEnter(mylock, 0))
{
try
{
// Do work
}
finally
{
Monitor.Exit(mylock);
}
}
}
However, before entering myFunction, I would like to know if the object is locked so that I can do something else. So I did:
public bool IsLocked
{
get { return !Monitor.TryEnter(locker); }
}
Will this work, or is it locking the object?
It will lock the object if it isn't locked, and won't release the lock until you call exit. If the lock is already taken by another thread it won't acquire the lock, but if you're making the call on the thread that acquired the lock in the first place then TryEnter will succeed.
To get around this you could use a flag and the interlocked functions:
object var mylock = new object();
long isLocked;
public void myFunction()
{
if (Monitor.TryEnter(mylock, 0))
{
Interlocked.Exchange(ref isLocked, 1);
try
{
// Do work
}
finally
{
Interlocked.Exchange(ref isLocked, 0);
Monitor.Exit(mylock);
}
}
}
public bool IsLocked
{
get { return Interlocked.Read(ref isLocked)==0; }
}
Related
For sake of practice, I am trying to write a solution to the readers-writers problem.
The expected behavior should be that multiple reads can run concurrently, but writes need to wait for all readers to finish.
My solution is below in Read(), Write() methods, and the book I am referencing suggests Write2() for the writers.
1) I don't entirely understand why they chose to implement this way, specifically why the read lock is trying to be acquired again, after being awoken when numOfReaders == 0.
Is that to give readers priority, if one came right after Write acquired the read lock, and right before it actually wrote anything?
2) Are there any other issues with the my suggested Write implementation?
Thanks!!
class ReaderWriter
{
private int numOfReaders = 0;
private readonly object readLock = new object();
private readonly object writeLock = new object();
public void Read()
{
lock (readLock)
{
this.numOfReaders++;
}
// Read stuff
lock (readLock)
{
this.numOfReaders--;
Monitor.Pulse(readLock);
}
}
// My solution
public void Write()
{
lock (writeLock)
{
lock (readLock)
{
while (this.numOfReaders > 0)
{
Monitor.Wait(readLock);
}
// Write stuff
}
}
}
// Alternative solution
public void Write2()
{
lock (writeLock)
{
bool done = false;
while (!done)
{
lock (readLock)
{
if (this.numOfReaders == 0)
{
// Write stuff
done = true;
}
else
{
while (this.numOfReaders > 0)
{
Monitor.Wait(readLock);
}
}
}
}
}
}
}
I have partial C# code for a blocking queue that looks like this:
private bool flushed;
private object _locker = new object();
public bool Flushed
{
get { lock (_locker) { return flushed; } }
set
{
lock (_locker)
{
flushed = value;
Monitor.Pulse(queue);
}
}
}
The Monitor.Pulse method has a Monitor.Wait counterpart in the Dequeue() method of the blocking queue.
I want to add a method that signals end of data, which checks for the Flush condition. It will look something like this:
public bool EndOfData
{
get { lock (_locker) { return Flushed && (queue.Count == 0); } }
}
Here is my question. Should I call the Flushed property as shown in the code above (taking a nested lock), or is it sufficient to refer to the private member variable flushed directly, as shown below, using only a single lock?
public bool EndOfData
{
get { lock (_locker) { return flushed && (queue.Count == 0); } }
}
I don't think it makes a difference, personally I would use the nested version.
I think if anything changes in the actual property by using it, Flushed, you ensure
that everything is good to go.
But I truly believe this is a preference call.
I have objects, they get locks. I want to test if they are locked without acquiring a lock. The idea is if I TryEnter() then i have to Exit() if true to only check the lock correctly.
Seems like a really basic question, how is it done?
What possible information can you get from knowing the lock was unlocked back when you looked at it? By the time you make a decision based on that information, the lock may be already taken.
Because the lock statement is equivalent to:
System.Threading.Monitor.Enter(x);
try {
...
}
finally {
System.Threading.Monitor.Exit(x);
}
Can you just do this?
bool ObjectWasUnlocked(object x)
{
if(System.Threading.Monitor.TryEnter(x))
{
System.Threading.Monitor.Exit(x);
return true;
}
else
{
return false;
}
}
Note that I'm naming this function "ObjectWasUnlocked" as opposed to "ObjectIsUnlocked". There is no guarantee that it will still be unlocked when the function has returned.
I was wondering the same thing while trying to audit my code for correct locking. I came up with a method using a second thread. If the lock is available to the calling thread, but unavailable to a second thread, it must be held by the first.
/// <summary>
/// Utiltity for checking if a lock has already been acquired.
/// WARNING: This test isn't actually thread-safe,
/// it's only really useful for unit tests
/// </summary>
private static bool ObjectIsAlreadyLockedByThisThread(object lockObject)
{
if (!Monitor.TryEnter(lockObject))
{
// another thread has the lock
return false;
}
Monitor.Exit(lockObject);
bool? LockAvailable = null;
var T = new Thread(() =>
{
if (Monitor.TryEnter(lockObject))
{
LockAvailable = true;
Monitor.Exit(lockObject);
}
else
{
LockAvailable = false;
}
});
T.Start();
T.Join();
return !LockAvailable.Value;
}
// Tests:
public static void TestLockedByThisThread()
{
object MyLock = new object();
lock (MyLock)
{
bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);
Debug.WriteLine(WasLocked); // prints "True"
}
}
public static void TestLockedByOtherThread()
{
object MyLock = new object();
var T = new Thread(() =>
{
lock (MyLock)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
}
});
T.Start();
Thread.Sleep(TimeSpan.FromSeconds(1));
bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);
T.Join();
Debug.WriteLine(WasLocked); // prints "False"
}
public static void TestNotLocked()
{
object MyLock = new object();
bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock);
Debug.WriteLine(WasLocked); // prints "False"
}
I wouldn't use this in production code - there's a race condition that could blow up. However, my unit tests are mostly single threaded, so this was useful.
Here is a related question
Checking whether the current thread owns a lock
The conclusion there was 'you can't'
I wrote a multithreaded application for .NET and in a very important portion of code I have the following:
public class ContainerClass {
private object list_lock;
private ArrayList list;
private object init_lock = new object();
private ThreadClass thread;
public void Start() {
lock(init_lock) {
if (thread == null) {
thread = new ThreadClass();
...
}
}
}
public void Stop() {
lock(init_lock) {
if (thread != null) {
thread.processList(0);
thread.finish();
thread.waitUntilFinished();
thread = null;
} else {
throw new ApplicationException("Assertion failed - already stopped.");
}
...
}
}
private class ThreadedClass {
private ContainerClass container;
private Thread thread;
private bool finished;
private bool actually_finished;
public ThreadedClass(ContainerClass container) {
this.container = container;
thread = new Thread(run);
thread.IsBackground = true;
thread.Start();
}
private void run() {
bool local_finished = false;
while (!local_finished) {
ArrayList to_process = null;
lock (container.list_lock) {
if (container.list.Count > 0) {
to_process = new ArrayList();
to_process.AddRange(container.list);
}
}
if (to_process == null) {
// Nothing to process so wait
lock (this) {
if (!finished) {
try {
Monitor.Wait(this);
} catch (ThreadInterruptedException) {
}
}
}
} else if (to_process.Count > 0) {
// Something to process, so go ahead and process the journals,
int sz = to_process.Count;
// For all elements
for (int i = 0; i < sz; ++i) {
// Pick the lowest element to process
object obj = to_process[i];
try {
// process the element...
...
} catch (IOException e) {
...
// If there is an error processing the best thing to do is finish
lock (this) {
finished = true;
}
}
}
}
lock (this) {
local_finished = finished;
// Remove the elements that we have just processed.
if (to_process != null) {
lock (container.list_lock) {
int sz = to_process.Count;
for (int i = 0; i < sz; ++i) {
container.list.RemoveAt(0);
}
}
}
// Notify any threads waiting
Monitor.PulseAll(this);
}
}
lock (this) {
actually_finished = true;
Monitor.PulseAll(this);
}
}
public void waitUntilFinished() {
lock (this) {
try {
while (!actually_finished) {
Monitor.Wait(this);
}
} catch (ThreadInterruptedException e) {
throw new ApplicationException("Interrupted: " + e.Message);
}
}
}
public void processList(int until_size) {
lock (this) {
Monitor.PulseAll(this);
int sz;
lock (container.list_lock) {
sz = container.list.Count;
}
// Wait until the sz is smaller than 'until_size'
while (sz > until_size) {
try {
Monitor.Wait(this);
} catch (ThreadInterruptedException ) {
}
lock (container.list_lock) {
sz = container.list.Count;
}
}
}
}
}
}
As you can see, the thread waits until the collection is empty but it seems that the synchronization clashes forbids the thread to enter at the point (the only one in the whole code) where an element is removed from the collection list in the ContainerClass.
This clash provokes the code to never return and the application to continue running if the method processList is called with the value of until_size of 0.
I beg any better developer than me (and I guess there are a lot out there) to help me fixing this small piece of code, since I really can't understand why the list isn't decremented...
Thank you very much from the bottom of my heart.
PS. I would like to underline that the code works perfectly for all the time: the only situation in which it brakes it's when calling thread.processList(0) from ContainerClass.Stop().
Could the problem be that you are locking the ThreadClass object itself rather than a synchronizing object?
Try adding another private variable to lock on:
private static readonly object lockObject = new object()
and replace all the calls of lock(this) with lock(lockObject)
MSDN clearly advises against what your doing:
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.
Edit:
I think I see a deadlock condition. If you call run() when there are no objects to process, or you get to no objects to process, you lock(this), then call Monitor.Wait(this) and the thread waits:
if (to_process == null) {
// Nothing to process so wait
lock (this) { /* nothing's going to get this lock again until Monitor.PulseAll(this) is called from somewhere */
if (!finished) {
try {
Monitor.Wait(this); /* thread is waiting for Pulse(this) or PulseAll(this) */
} catch (ThreadInterruptedException) {
}
}
}
}
If you are in this condition when you call Container.Stop(), when ThreadProcess.processList(int) is called, you call lock(this) again, which can't enter the section because the run() method still has the lock:
lock (this) { /* run still holds this lock, waiting for PulseAll(this) to be called */
Monitor.PulseAll(this); /* this isn't called so run() never continues */
int sz;
lock (container.list_lock) {
sz = container.list.Count;
}
So, Monitor.PulseAll() can't be called to free the waiting thread in the run() method to exit the lock(this) area, so they are deadlocked waiting on each other. Right?
I think you should try to explain better what you actually want to achieve.
public void processList(int until_size) {
lock (this) {
Monitor.PulseAll(this);
This looks very strange as you should call the Monitor.Pulse when changing the lock state and not when beginning with locking.
Where are you creating the worker threads - this section is not clear as I see only Thread.Start()?
Btw I would advise you to look at PowerCollections - maybe you find what you need there.
The following C# class is used in a multithreaded enviroment. I removed very much of the actual code. The problem occurs when calling MethodA and MethodB almost simultaneously. The order of the lock in the IsDepleted property doesn't solves the problem. Removing lock(WaitingQueue) from the IsDepleted property solves the deadlock, but this solution causes a problem when another thread adds/removes an item from the WaitingQueue between the WaitingQueue.Count == 0 and Processing.Count == 0 statements.
using System.Collections.Generic;
class Example
{
bool IsDepleted
{
get
{
lock (Processing)
{
lock (WaitingQueue)
{
return WaitingQueue.Count == 0
&& Processing.Count == 0;
}
}
}
}
private readonly List<object> Processing = new List<object>();
private readonly Queue<object> WaitingQueue = new Queue<object>();
public void MethodA(object item)
{
lock (WaitingQueue)
{
if (WaitingQueue.Count > 0)
{
if (StartItem(WaitingQueue.Peek()))
{
WaitingQueue.Dequeue();
}
}
}
}
public void MethodB(object identifier)
{
lock (Processing)
{
Processing.Remove(identifier);
if (!IsDepleted)
{
return;
}
}
//Do something...
}
bool StartItem(object item)
{
//Do something and return a value
}
}
It depends if you want a quick fix or a rigorous fix.
A quick fix would be just to use one lock object in all cases.
e.g. private readonly object _lock = new object();
And then just lock on that. However, depending on your situation, that may impact performance more than you can accept.
I.e. your code would become this:
using System.Collections.Generic;
class Example
{
private readonly object _lock = new object();
bool IsDepleted
{
get
{
lock (_lock)
{
return WaitingQueue.Count == 0
&& Processing.Count == 0;
}
}
}
private readonly List<object> Processing = new List<object>();
private readonly Queue<object> WaitingQueue = new Queue<object>();
public void MethodA(object item)
{
lock (_lock)
{
if (WaitingQueue.Count > 0)
{
if (StartItem(WaitingQueue.Peek()))
{
WaitingQueue.Dequeue();
}
}
}
}
public void MethodB(object identifier)
{
lock (_lock)
{
Processing.Remove(identifier);
if (!IsDepleted)
{
return;
}
}
//Do something...
}
bool StartItem(object item)
{
//Do something and return a value
}
}
Take the Processing lock in method A and the WaitingQueue lock in method B (in other words, make it look like the first block of code). That way, you always take the locks in the same order and you'll never deadlock.
Simplify your code and use only a single object to lock on. You could also replace your locks with:
Monitor.TryEnter(Processing,1000)
this will give you a 1 second timeout. So essentially:
if (Monitor.TryEnter(Processing, 1000))
{
try
{
//do x
}
finally
{
Monitor.Exit(Processing);
}
}
Now you won't stop the deadlock but you can handle the case where you don't get a lock.