Not really language specific, but I have this in C#:
public static void StartJob() {
ThreadPool.QueueUserWorkItem(s => {
if (Monitor.TryEnter(_lock)) {
ProcessRows();
Monitor.Exit(_lock);
}
}
);
ProcessRows() processes and removes rows in a database until all rows are removed. At program launch and whenever a row is added to the database elsewhere in the program, StartJob is called, to ensure all rows are processed without blocking the program. Now if a row is added at exactly the same time as StartJob is about to release the lock, it will not be processed.
How do I ensure that all rows are processed? I prefer not to have ProcessRows() run unless rows are added.
Don’t lock around the method; lock within the method using a flag that says whether you’re running or not.
One implementation might look like the code below – in this case I’ve moved all the logic into
ProcessRowsand made the method return immediately if it’s already running.With this structure, it’s impossible for the
whileloop to complete without setting_isRunning = false– if this weren’t the case, there would be a race condition if the loop completed just as another instance of the method started. Equally, when the method is called, it will always enter the loop and set_isRunning = truebefore another instance gets a chance to execute.