Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
using System;
using System.Threading;
namespace MultiThreadedPrinting
{
public class Printer
{
public void PrintNumbers()
{
// Отобразить информацию о потоке.
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()
Должно быть совершенно ясно, что здесь присутствуют проблемы. В то время как каждый поток сообщает экземпляру
Printer
System.Threading
Синхронизация с использованием ключевого слова lock языка C#
Первый прием, который можно применять для синхронизации доступа к разделяемым ресурсам, предполагает использование ключевого слова
lock
lock