不是特定语言,但我在C#中有这个:
public static void StartJob() {
ThreadPool.QueueUserWorkItem(s => {
if (Monitor.TryEnter(_lock)) {
ProcessRows();
Monitor.Exit(_lock);
}
}
);
ProcessRows()
处理并删除数据库中的行,直到删除所有行。在程序启动时,只要在程序的其他位置向数据库添加行,就会调用StartJob
,以确保处理所有行而不阻塞程序。现在,如果在StartJob
即将释放锁的同时添加一行,则不会处理该行。
如何确保处理所有行?除非添加行,否则我不希望ProcessRows()
运行。
答案 0 :(得分:2)
不要锁定方法;使用一个标记来锁定方法,该标记表示您是否正在运行。
一个实现可能看起来像下面的代码 - 在这种情况下,我已将所有逻辑移动到ProcessRows
并使该方法立即返回,如果它已经在运行。
public static bool _isRunning = false;
public static void StartJob()
{
ThreadPool.QueueUserWorkItem(s => { ProcessRows(); })
}
public static void ProcessRows()
{
Monitor.Enter(_lock);
if (_isRunning)
{
Monitor.Exit(_lock);
return;
}
_isRunning = true;
while (rowsToProcess)
{
Monitor.Exit(_lock);;
// ... do your stuff
Monitor.Enter(_lock);
}
_isRunning = false;
Monitor.Exit(_lock);
}
使用这种结构,while
循环不可能在没有设置_isRunning = false
的情况下完成 - 如果不是这种情况,如果循环完成就像另一个实例一样,就会出现竞争条件方法开始了。同样,当调用该方法时,它将始终进入循环并在另一个实例有机会执行之前设置_isRunning = true
。