// Отобразить информацию о потоке.
Console.WriteLine("-> {0} is executing PrintNumbers()",
Thread.CurrentThread.Name);
// Вывести числа.
for (int i = 0; i < 10; i++)
{
// Приостановить поток на случайный период времени.
Random r = new Random();
Thread.Sleep(1000 * r.Next(5));
Console.Write("{0}, ", i);
}
Console.WriteLine();
}
}
}
Вызывающий код отвечает за создание массива из десяти (уникально именованных) объектов Thread, каждый из которых вызывает метод Printer:
using System;
using System.Threading;
using MultiThreadedPrinting;
Console.WriteLine("*****Synchronizing Threads *****\n");
Printer p = new Printer();
// Создать 10 потоков, которые указывают на один.
// и тот же метод того же самого объекта
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
threads[i] = new Thread(new ThreadStart(p.PrintNumbers))
{
Name = $"Worker thread #{i}"
};
}
// Теперь запустить их все.
foreach (Thread t in threads)
{
t.Start();
}
Console.ReadLine();
Прежде чем взглянуть на тестовые запуски, кратко повторим суть проблемы. Первичный поток внутри этого домена приложения начинает свое существование с порождения десяти вторичных рабочих потоков. Каждому рабочему потоку указывается на необходимость вызова метода PrintNumbers() Printer. Поскольку никаких мер для блокировки разделяемых ресурсов данного объекта (консоли) не предпринималось, есть неплохой шанс, что текущий поток будет вытеснен до того, как метод PrintNumbers() выведет полные результаты. Из-за того, что не известно в точности, когда подобное может произойти (если вообще произойдет), будут получены непредсказуемые результаты. Например, вывод может выглядеть так:
*****Synchronizing Threads *****
-> Worker thread #3 is executing PrintNumbers()
-> Worker thread #0 is executing PrintNumbers()
-> Worker thread #1 is executing PrintNumbers()
-> Worker thread #2 is executing PrintNumbers()
-> Worker thread #4 is executing PrintNumbers()
-> Worker thread #5 is executing PrintNumbers()
-> Worker thread #6 is executing PrintNumbers()
-> Worker thread #7 is executing PrintNumbers()
-> Worker thread #8 is executing PrintNumbers()
-> Worker thread #9 is executing PrintNumbers()
0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 3, 1, 2, 2, 2, 1, 2,
1, 1, 2, 2, 3, 3, 4,
3, 3, 2, 2, 3, 4, 3, 4, 5, 4, 5, 4, 4, 3, 6, 7, 2, 3, 4, 4, 4, 5, 6, 5,
3, 5, 8, 9,
6, 7, 4, 5, 6, 6, 5, 5, 5, 8, 5, 6, 7, 8, 7, 7, 6, 6, 6, 8, 9,
8, 7, 7, 7, 7, 9,
6, 8, 9,
8, 9,
9, 9,
8, 8, 7, 8, 9,
9,
9,
Запустите приложение еще несколько раз. Скорее всего, каждый раз вы будете получать отличающийся вывод.
На заметку! Если получить непредсказуемый вывод не удается, увеличьте количество потоков с 10 до 100 (например) или добавьте в код еще один вызов Thread.Sleep(). В конце концов, вы столкнетесь с проблемой параллелизма.