哪个线程将首先进入临界区?

时间:2012-09-05 17:19:48

标签: c# .net multithreading

假设多个线程定期执行下面的DoWork()方法。假设在某个时刻,两个线程几乎同时开始执行此方法,因此两个本地时间戳对象中的一个比另一个更大。

ICollection collection = // ...

public void DoWork()
{
    DateTime timestamp = DateTime.Now;

    lock(collection.SyncRoot)
    {
        // critical section
    }
}

如果线程A的特征是时间戳等于 t1 ,而线程B的特征是时间戳 t2 等于 t1 + 1 tick < / em>,然后线程A首先需要访问临界区。

.NET如何管理多个线程对关键部分的访问?它是否将访问请求放入队列中,以便它们按时间顺序排列?换句话说,是否根据线程访问请求的顺序保证对关键部分的访问?

2 个答案:

答案 0 :(得分:6)

绝对不能保证线程执行的顺序以及首先获得关键部分的线程。

请注意,即使线程的优先级也不能保证顺序 - 不同的内核/ CPU可以在完全相同的时间以不同的优先级执行线程,并且任何线程都可以首先到达并获得关键部分。

注2:线程也可以在任意时刻被调度执行/等待,因此同一线程中的两个不同操作彼此相邻的事实并不意味着它们将一个接一个地执行而没有延迟之间。在你的情况下,这意味着线程A可以在获得时间戳后立即停止,并且计划执行一段时间后的线程B将很容易获得更晚的时间戳,但首先进入关键部分。

答案 1 :(得分:4)

你正在做一个很高的假设,一个永远让程序员遇到线程麻烦的假设。首先获得时间戳的线程当然也不能保证首先进入锁。只有赔率很高,他们不是100%。线程被操作系统调度程序抢占。哪个线程可以中断,包括刚开始执行Monitor.Enter()方法调用的线程。然后,调度决策可以暂停A并允许B首先获得锁定。

调度程序也不需要修改订单。执行A的核心可能在其数据高速缓存中没有“集合”对象引用,在等待内存总线允许执行B的核心提前竞争时足够长时间停止核心。 “种族”这个词是合适的,这里做出错误的假设会导致你的代码中出现种族错误。

锁定机制由处理器实现,处理器是唯一可以确保没有“同一时间”的实体。每个多核cpu都实现Compare-and-swap原子指令。您可以在this answer中看到.NET使用的版本。