2009-08-25 3 views
6

Скажем, у меня есть следующий кодОжидают ли потоки FIFO?

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

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

Тогда давайте говорить, что в то время как thread1 имеет блокировку thread2 пытается запустить 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 –

-1

Он будет ждать, и они не будут в том же порядке.

В зависимости от ваших потребностей, вы можете иметь более высокую производительность, если вы посмотрите на то, как ReaderWriterLock или нечто иное, чем просто lock

+1

Они не то же самое заказ. –

3

Это не ясно из вашего кода, как это myobj получить, чтобы быть видимым внутри mymethod. Похож, что var myobj - это локальная переменная стека в области декларации (начиная с var). В этом случае может быть, что каждый поток будет иметь отдельный экземпляр, а mymethod не будет блокироваться.

Update

О целом FIFO аргумент, некоторые справочную информацию обязательно: CLR не обеспечивает Syncronization. Это хост CLR , который предоставляет это как услугу для среды выполнения CLR. Хост реализует IHostSyncManager и другие интерфейсы и предоставляет различные примитивы syncronisation. Это может показаться слишком важным, поскольку наиболее распространенным хостом является типичный хост приложения (т. Е. Вы компилируете в и exe), и это делит всю синхронизацию с ОС (ваши старые примитивы книги Petzold в Win32 API). Однако есть, по крайней мере, еще два основных аспекта хостинга: один ASP.Net (я не уверен, что это делает) и SQL Server. То, что я могу сказать наверняка, заключается в том, что SQL Server предоставляет все примитивы на вершине SOS (который в основном является пользователем более операционной системы), никогда не касаясь примитивов ОС, а примитивы SOS несправедливы по дизайну, чтобы избежать конвоев блокировки (т.е. guranteed no FIFO). Поскольку ссылка в другом ответе уже была указана, примитивы ОС начали также обеспечивать несправедливое поведение по той же причине, что и избежать блокировки конвоев.

Для получения дополнительной информации о блокировке конвоях вы должны прочитать статьи Rick Vicik в Designing Applications for High Performance:

замок Convoy

ФИФО замки гарантируют справедливость и вперед прогресса за счет вызывая блокировку конвои , Термин первоначально означал несколько потоков исполнителей ту же часть коды, как группу, что приводит к более высоким столкновениям чем если бы они были случайным образом распределены по всему коду (так же, как автомобили быть сгруппированы в пакеты светофора).Специфическое явление , о котором я говорю, хуже , потому что, как только он образует неявное , передача права собственности на блокировку сохраняет потоки в блокировке.

Для иллюстрации рассмотрим пример , где нить удерживает замок, а выгружается при удерживании замка. Результат - все остальные темы будет накапливаться в списке ожидания для этого lock. Когда превентивная нить (замок владелец в это время) снова запускается и освобождает замок, он автоматически передает права собственности на замок на первый поток в ожидании . Этот поток может не работать в течение некоторое время, но галочки «удерживать время» . Предыдущий владелец обычно запрашивает блокировку снова перед список ожидания очищается, увековечению конвоя

+0

Вы правы, это статический объект в статическом объекте, я написал слишком быстро. Исправит это сейчас – Matt

0

окна и CLR попытка все возможное, чтобы гарантировать справедливость (порядок FIFO) в ожидании. Тем не менее, есть определенные сценарии, в которых порядок потоков, ожидающих блокировки, может быть изменен, в основном, вращается вокруг предупреждающих ожиданий, и вся блокировка потока 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); 
      } 
     } 
    } 
} 

Execution будет 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 

Как ча видеть процесс блокировки рич отличается, что замок войти.

Смежные вопросы