Джо Даффи (автор Параллельное программирование в Windows) пишет в в этой статье в блоге, что Thread.Sleep(1) является предпочтительным по сравнению с Thread.Sleep(0), потому что он будет приостанавливаться для потоков с одним и более низким приоритетом, а не только равными приоритетными потоками, как для Thread.Sleep(0).
. NET-версия MSDN говорит, что Thread.Sleep(0) является специальным, он приостанавливает этот поток и разрешает другие ожидающие потоки выполнить. Но он ничего не говорит о Thread.Sleep(1) (для любой версии .NET).
Итак, Thread.Sleep(1) действительно делает что-то особенное?
Фон:
Я обновляю свои знания о параллельном программировании. Я написал код С#, чтобы наглядно показать, что приращения и декременты pre/post не являются атомарными и, следовательно, не являются потокобезопасными.
Чтобы избежать необходимости создавать сотни потоков, я помещаю Thread.Sleep(0) после увеличения общей переменной, чтобы заставить планировщика запустить другой поток. Эта регулярная замена потоков делает неатомарную природу до/после приращения/уменьшения более очевидной.
Thread.Sleep(0), по-видимому, не вызывает дополнительной задержки, как и ожидалось. Однако, если я изменил это на Thread.Sleep(1), он, похоже, вернется к нормальному режиму сна (например, я получаю примерно минимум 1 мс задержки).
Это будет означать, что хотя Thread.Sleep(1) может быть предпочтительнее, любой код, который использует его в цикле, будет работать намного медленнее.
Этот вопрос SO "Может ли кто-нибудь объяснить это интересное поведение с помощью Sleep (1)?" является своего рода релевантным, но он сосредоточен на С++ и просто повторяет руководство в Статья Джо Дэффи в блоге.
Здесь мой код для всех, кто интересуется (скопирован из LinqPad, поэтому вам может понадобиться добавить класс вокруг него):
int x = 0;
void Main()
{
List<Thread> threadList=new List<Thread>();
Stopwatch sw=new Stopwatch();
for(int i=0; i<20; i++)
{
threadList.Add(new Thread(Go));
threadList[i].Priority=ThreadPriority.Lowest;
}
sw.Start();
foreach (Thread thread in threadList)
{
thread.Start();
}
foreach (Thread thread in threadList)
{
thread.Join();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Thread.Sleep(200);
Console.WriteLine(x);
}
void Go()
{
for(int i=0;i<10000;i++)
{
x++;
Thread.Sleep(0);
}
}