I have a web app which has a number of different “worker” threads. These threads need to write to a single shared log file. What is the best practice for doing this without getting into trouble with deadlocks, race conditions, barometric pressure changes, etc.?
Currently I have a single “WriteToLog” method on the app class. Each thread calls that. WriteToLog just opens a TextOutputStream, does a WriteLine, and closes it.
Will I get into trouble with this approach? If so, what’s the best practice for doing something like this?
The semaphore itself belongs in the app class, right?
Then in the threads, they call Signal and Release on the app.semaphore.
What happens if a thread crashes after calling signal but before Release? I see in the CriticalSection docs it says “If a thread that has a lock crashes, the lock is not released.” Does the same apply to Semaphore, and if so how could I release the crashed lock?
The Semaphore can belong to the method exactly as I showed it.
The Thread would only “crash” in that method if the method itself crashed or if you happened to kill the Thread right when it was in that method. There are two ways to deal with that:
Add an Exception handler to that method. Something like this:
static s as new Semaphore
s.Signal
// Write to log
s.Leave
Exception err as RuntimeException
s.Leave
raise err
(Better) Create a wrapper class for the Semaphore, SemaphoreHolder, that Enters the Semaphore in its Constructor and Leaves it in its Destructor. The code would look something like this
static s as new Semaphore
dim holder as new SemaphoreHolder( s )
// Write to log
The Semaphore will be released no matter how holder goes nil, be it the end of the method or an Exception.
Thanks. Just to clarify here, I DO think I need the thread on the app class.
I don’t have one thread class that I’m instantiating over and over; I have several different classes, all of which are threads, that do different things.
So I think I have to have the semaphore on the app class, right? Otherwise the different thread types will each have their own unique semaphore, which isn’t very useful.
I guess I’m not understanding something. If each of my thread types is a class, and I define a static variable inside that class, then it’s not visible by other classes. So how does “static” help in this instance? The semaphore needs to be visible by all in order to be effective, no?
The Static variable would be defined within that method. You can put a property into the App class instead if you prefer, but that’s extra code that will have exactly the same result.
Since each Thread uses that WriteToLog method, only one Thread at a time will be able write to the log at a time.