我想实现一个线程安全列表,但必须确保整个操作块的线程安全,而不仅仅是单个操作(例如添加、删除等)。用例应如下所示:
list.Lock();
list.Add(sth);
list.RemoveAt(4);
list.Unlock();
我希望列表要求锁定任何操作。例如:
list.Add(sth);
在没有事先锁定的情况下调用应该会导致异常。这就是我不使用该lock()
语句的原因 - 锁定检查对于此解决方案至关重要。
使用 Monitor 实现这样的列表并不难——但只有在想要检查列表是否被锁定之前。我想到了以下场景:
// Inside list class
private object lockObject;
private bool locked;
public void Lock()
{
Monitor.Enter(lockObject);
locked = true;
}
public void Unlock()
{
Monitor.Exit(lockObject);
locked = false;
}
不幸的是,这段代码很容易出现竞争条件——无论locked
是在进入或离开临界区之前还是之后设置。
另一种方法涉及到使用 TryEnter,但是这种方法实际上是在没有获得锁的情况下进入临界区,这也可能导致竞争条件。
我应该如何实现这个机制以保证线程安全,以及如何在检查列表是否被锁定时避免竞争条件?