mlapaglia
mlapaglia

Reputation: 902

Lock Sharing Between Classes

I am trying to find the best practice for sharing a lock file between multiple classes. Before this I was putting multiple functions inside the same class, so they could share a mutual lock file and a producer/consumer queue. The code is getting a bit longer than I'd like, and I want to break them up into individual classes. When I do this I am unable to share the lock files, or the queues to add/remove the commands from.

I need to have a UI thread that accepts input from the user, and then places the commands into a locked queue that the worker threads can pull from. I would like to place the UI thread and the worker functions into different classes to keep my code nicely organized.

Sorry if this is too vague. Is there a way to do this that doesn't break good design technique?

Upvotes: 5

Views: 4999

Answers (3)

Michael Hays
Michael Hays

Reputation: 6908

If the locks are shared between multiple classes, and the "owner" is not readily identifiable, then place those locks into a class that is shared.

public class MyLocks { ... all your locks ... }

Then when you initialize your classes that utilize the locks, pass them into the constructor. Alternatively, you can have the classes instantiate MyLocks on their own, and then expose it as a property which you can then use in subsequent construction.

...
var a = new ClassWithLocks();
var b = new ClassWithLocks(a.MyLocks);
var b = new SomeOtherClassWithLocks(a.MyLocks);
...

The takeaway is to place the locks into their own unit.

Update

An additional benefit of placing multiple locks into their own class is that you can explicitly create methods for seizing and releasing locks. For example:

void PushLock(string myToken, LOCK_ENUM theLockIWant);
void PopLock(string myToken, LOCK_ENUM theLockIWant);

Now a particular class or operation can request locks, but if they try to grab a lock whose enumerator is less than the lock they are requesting, you can throw an exception. This is important when you require multiple locks to perform an operation as you can ensure that the locks are seized and released in order, which is one of the most common culprits in deadlocks.

Upvotes: 2

bkdc
bkdc

Reputation: 524

What's a 'lock file'? Are you using the FileStream Lock / Unlock methods? If so, you might consider whether you really need them.

Back to locking: I think that a simple, shared, ReaderWriterLock(Slim) should do in most cases (and yours). Michael outlined the basic idea - you should add a singleton on top of that - it would simplify your project and life a lot (no need to pass the instance around, easier to debug).

Take care with those threads, deadlocks are not fun!

PS: It might be obvious (to some) but locks are only effective when dealing with multiple threads.

Upvotes: 1

Hans
Hans

Reputation: 13030

You could use the thread safe ConcurrentQueue from the System.Collection.Concurrent namespace and share this queue between your UI thread and the worker threads like so:

ConcurrentQueue<T> workItems = new ConcurrentQueue<T>();

UIThreadClass uiThread = new UIThreadClass(workItems);

WorkerThreadClass workerThread = new WorkerThread(workItems);

uiThread.Run();

workerThread.Run();

In your worker thread class you could periodically check the work item queue for new items by using the method TryPeek(). For a detailed description on the ConcurrentQueue refer to MSDN.

Hope, this helps.

Upvotes: 1

Related Questions