线程在锁定FIFO上等待吗?

假设我有以下代码

static class ... { static object myobj = new object(); static void mymethod() { lock(myobj) { // my code.... } } } 

然后让我们说当thread1有锁定时,thread2尝试运行mymethod。 是否会等待释放锁定或抛出exception?

如果它确实等待,是否确保订单,以便如果其他线程进入它们是FIFO?

更新了我的答案:它们排队,但订单不保证是FIFO。

看看这个链接: http : //www.albahari.com/threading/part2.aspx

从你的代码中不清楚myobj如何在mymethod可见。 看起来var myobj是声明范围内的本地堆栈变量(因为是var )。 在这种情况下,可能每个线程都有一个单独的实例,而mymethod不会阻塞。

更新

关于整个FIFO参数,一些背景信息是必要的:CLR不提供同步。 它是CLR 主机 ,它将此作为服务提供给CLR运行时。 主机实现IHostSyncManager和其他接口,并提供各种同步原语。 这似乎是相关的,因为最常见的主机是典型的应用程序主机(即你编译成和exe),这会将所有同步转移到操作系统(你在Win32 API中的旧的Petzold书原语)。 但是至少还有两个主要的托管环境:ASP.Net一个(我不确定它是什么)和SQL Server。 我可以肯定的是,SQL Server提供了SOS (基本上是用户更多操作系统)的所有原语,从不接触OS原语,并且SOS原语在设计上是不公平的,以避免锁定车队(即。保证没有FIFO)。 正如其他响应中的链接已经指出的那样,操作系统原语也开始提供不公平的行为,原因与避免锁定车队相同。

有关锁定车队的更多信息,您应该阅读设计应用程序高性能的Rick Vicik文章:

锁定车队

FIFO锁定保证了公平性和前进性,但却导致锁定车队。 该术语最初意味着执行代码的相同部分的若干线程作为一组导致比在整个代码中随机分布的更高的冲突(很像汽车被交通信号灯分组成数据包)。 我正在谈论的特殊现象更糟糕,因为一旦它形成了锁拥有的隐式切换,就会使线程保持锁定状态。

为了说明,请考虑一个线程持有锁并在持有锁时被抢占的示例。 结果是所有其他线程将堆积在该锁的等待列表中。 当被抢占的线程(此时锁定所有者)再次运行并释放锁定时,它会自动将锁定的所有权交给等待列表中的第一个线程。 该线程可能无法运行一段时间,但“保持时间”时钟正在滴答作响。 之前的所有者通常在等待清单被清除之前再次请求锁定,从而使车队永久化

一个简单的例子告诉我们,订单不能保证是FIFO

  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace ConsoleApplication { class Program { private static Info info = new Info(); static void Main(string[] args) { Thread[] t1 = new Thread[5]; for (int i = 0; i < 5; i++) { t1[i] = new Thread(info.DoWork); } Thread[] t2 = new Thread[5]; for (int i = 0; i < 5; i++) { t2[i] = new Thread(info.Process); } for (int i = 0; i < 5; i++) { t1[i].Start(); t2[i].Start(); } Console.ReadKey(); } } class Info { public object SynObject = new object(); public void DoWork() { Debug.Print("DoWork Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); lock (this.SynObject) { Debug.Print("Thread Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Debug.Print("Thread Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); } } public void Process() { Debug.Print("Process Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); lock (this.SynObject) { Debug.Print("Process Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Debug.Print("Process Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); } } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace ConsoleApplication { class Program { private static Info info = new Info(); static void Main(string[] args) { Thread[] t1 = new Thread[5]; for (int i = 0; i < 5; i++) { t1[i] = new Thread(info.DoWork); } Thread[] t2 = new Thread[5]; for (int i = 0; i < 5; i++) { t2[i] = new Thread(info.Process); } for (int i = 0; i < 5; i++) { t1[i].Start(); t2[i].Start(); } Console.ReadKey(); } } class Info { public object SynObject = new object(); public void DoWork() { Debug.Print("DoWork Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); lock (this.SynObject) { Debug.Print("Thread Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Debug.Print("Thread Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); } } public void Process() { Debug.Print("Process Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); lock (this.SynObject) { Debug.Print("Process Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Debug.Print("Process Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); } } } } 

执行将继续执行此类操作

 Process Lock Reached: 15 Process Lock Enter: 15 DoWork Lock Reached: 12 Process Lock Reached: 17 DoWork Lock Reached: 11 DoWork Lock Reached: 10 DoWork Lock Reached: 13 DoWork Lock Reached: 9 Process Lock Reached: 18 Process Lock Reached: 14 Process Lock Reached: 16 Process Lock Exit: 15 Thread Lock Enter: 9 Thread Lock Exit: 9 Process Lock Enter: 14 Process Lock Exit: 14 Thread Lock Enter: 10 Thread Lock Exit: 10 Thread Lock Enter: 11 Thread Lock Exit: 11 Process Lock Enter: 16 Process Lock Exit: 16 Thread Lock Enter: 12 Thread Lock Exit: 12 Process Lock Enter: 17 Process Lock Exit: 17 Thread Lock Enter: 13 Thread Lock Exit: 13 Process Lock Enter: 18 Process Lock Exit: 18 

你可以看到,锁定输入的过程是不同的。

Windows和CLR尽力保证等待的公平性(FIFO顺序)。 但是,在某些情况下,可以更改等待锁定的线程的顺序,主要是围绕可警告的等待,并且所有CLR线程锁定都会使线程处于可警告状态。

出于所有实际目的,您可以假设订单是FIFO; 但请注意这个问题。

它会等待,但它们的顺序不一样。

根据您的需要,如果您查看ReaderWriterLock或者除了lock其他内容,您可能会获得更多性能