2009-08-25 87 views
6

比方说,我有以下代码线程是否在锁FIFO上等待?

static class ... 
{ 
    static object myobj = new object(); 

    static void mymethod() 
    { 
     lock(myobj) 
     { 
      // my code.... 
     } 
    } 
} 

然后让我们说,虽然线程1具有线程2试图运行的MyMethod锁。 它会等待锁释放或抛出异常吗?

如果确实等待,请确保顺序,以便如果有其​​他线程进来,它们是FIFO?

回答

8

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

退房此链接:http://www.albahari.com/threading/part2.aspx

+4

不一定,请参阅:http://stackoverflow.com/questions/961869/is-there-a-synchronization-class-that-guarantee-fifo-order-in-c/961904 – 2009-08-25 20:47:26

-1

它会等待,他们不会以相同的顺序。

根据您的需求,你可能会如果你看看像以外的ReaderWriterLock或东西有更多的表现只是lock

+1

他们是不一样的订购。 – 2009-08-25 20:56:22

3

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

更新

关于整个FIFO的说法,一些背景信息是必要的:在CLR不提供同步化。它是CLR 主机,它将此作为服务提供给CLR运行时。主机实现IHostSyncManager和其他接口并提供各种同步原语。由于最常见的主机是典型的应用程序主机(即,您编译进入并执行exe),所以这可能看起来并不合适,并且这会影响与操作系统(Win32 API中的旧Petzold书籍原语)的所有同步。但是至少有两个主要的托管环境:ASP.Net(我不确定这是什么)和SQL Server。我可以肯定地告诉的是,SQL Server提供的SOS的托普所有原始数据(这基本上是一个用户的多个操作系统),从来没有接触OS原语和SOS原语是由设计不公平,避免锁车队(即。保证没有先入先出)。正如另一个响应中的链接已经指出的那样,OS原语也开始提供不公平的行为,因为避免锁车队的原因。

有关锁定车队的更多信息,你应该在Designing Applications for High Performance阅读里克Vicik文章:

锁定康宏

FIFO锁保证公平,在 费用造成 向前进步锁定车队。术语 本意几个线程 执行代码的相同的部分 导致更高的碰撞 比如果它们在整个码被随机分布 的基团(很像 汽车正在由交通灯分成分组 )。我说的 现象更糟 ,因为一旦它形成隐含的 切换锁拥有保持锁步骤 线程。

举例说明,请考虑示例 ,其中一个线程持有一个锁,并且在持有该锁的同时 被抢占。 结果是所有其他线程 将堆积在该锁的等待列表上。当抢占线程(此时锁具 拥有者)再次运行 并释放锁定时, 会自动将 锁定的所有权移交到等待 列表上的第一个线程。该线程有时可能不运行 ,但“保持时间”时钟 正在等待。以前的主人 通常要求锁再次 之前的等待列表中清除出去, 延续车队

+0

你是对的,它是静态对象中的一个静态对象,我写得太快了。现在会解决它 – Matt 2009-08-25 20:51:09

0

Windows和CLR的尝试,竭力为保证公平等待的(先进先出顺序)。但是,在某些情况下,等待锁的线程顺序可以更改,主要围绕可警告等待进行,所有CLR线程锁都将线程置于可警告状态。

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

1

一个简单的例子告诉我们,为了不保证做到先进先出

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); 
      } 
     } 
    } 
} 

执行会PROCEDE这样

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 

东西正如你CA看到达到锁的过程是锁定不同输入。