2013-11-29 7 views
2

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

using System; 
using System.Diagnostics; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static int testVal = 0; 
     static void Main(string[] args) 
     { 
      const int ThreadsCount = 10000; 
      var watch = Stopwatch.StartNew(); 
      for (int i = 0; i < ThreadsCount; i++) 
      { 
       var myThread = new Thread(MainVoid); 
       myThread.Start(); 
      } 
      watch.Stop(); 
      Console.WriteLine("Test value ={0}", testVal); 
      Console.WriteLine("Ended in {0} miliseconds", watch.ElapsedMilliseconds); 
      Console.WriteLine("{0} miliseconds per thread ", (double)watch.ElapsedMilliseconds/ThreadsCount); 
     } 

     static void MainVoid() 
     { 
      Interlocked.Increment(ref testVal); 
     } 
    } 
} 

Выход:

Test value =10000 

Ended in 702 miliseconds 

0,0702 miliseconds per thread. 

Является ли мой код неправильно или создание нити так быстро и советы в книгах неверны? (Я вижу только некоторое потребление памяти на поток, но не время создания.)

+0

Ваши темы не работают, вы уверены, что они действительно начали? – blueberryfields

+1

@blueberryfields Interlocked.Increment (ref testVal); это работа! –

+3

Вы создали 10000 потоков за 0,7 секунды - это может быть быстро или может быть очень медленным, в зависимости от вашей задачи. Если вы можете решить одну и ту же задачу за 0,1 секунды без использования каких-либо потоков, то потоки будут медленными и не имеют никакого смысла. В противном случае потоки хороши. В принципе, это зависит. У создания темы действительно есть накладные расходы, независимо от того, можете ли вы себе это позволить, это реальная проблема. 0.07 миллисекунд на поток может быть много, если вы можете сделать то же самое быстрее, не создавая поток. Контекст имеет значение. – IVlad

ответ

2

Создание темы довольно медленно. Рассмотрим этот бит кода, который противопоставляет скорость делает вещи инлайн, и делать вещи, с несколькими потоками:

private void DoStuff() 
{ 
    const int ThreadsCount = 10000; 
    var sw = Stopwatch.StartNew(); 
    int testVal = 0; 
    for (int i = 0; i < ThreadsCount; ++i) 
    { 
     Interlocked.Increment(ref testVal); 
    } 
    sw.Stop(); 
    Console.WriteLine(sw.ElapsedTicks); 

    sw = Stopwatch.StartNew(); 
    testVal = 0; 
    for (int i = 0; i < ThreadsCount; ++i) 
    { 
     var myThread = new Thread(() => 
     { 
      Interlocked.Increment(ref testVal); 
     }); 
     myThread.Start(); 
    } 
    sw.Stop(); 
    Console.WriteLine(sw.ElapsedTicks); 
} 

В моей системе, делая это рядный требует 200 тиков. С потоками это почти 2 миллиона клещей. Поэтому использование потоков здесь занимает примерно 10 000 раз. Я использовал ElapsedTicks здесь, а не ElapsedMilliseconds, потому что с ElapsedMilliseconds вывод для встроенного кода был 0. Версия потоков занимает около 700 миллисекунд. Контекстные коммутаторы стоят дорого.

Кроме того, ваш тест в корне ошибочен, потому что вы явно не дожидаетесь завершения всех потоков до сбора результата. Вполне возможно, что вы можете вывести значение testVal до того, как последний поток завершит его увеличение.

Если код синхронизации, кстати, вы обязательно должны запустить его в режиме деблокирования без прикрепленного отладчика. В Visual Studio используйте Ctrl + F5 (запуск без отладки).

+0

На самом деле вы не начали нить, не должен ли быть 'myThread.Start()' во втором цикле? – sthotakura

+0

@sthotakura: Вы правы! Это было неловко. Я исправил код и описание. –

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