Должно быть совершенно ясно, что здесь присутствуют проблемы. В то время как каждый поток сообщает экземпляру Printer
System.Threading предлагает несколько типов, связанных с синхронизацией. В языке C# также предусмотрено ключевое слово для синхронизации разделяемых данных в многопоточных приложениях.Синхронизация с использованием ключевого слова lock языка C#
Первый прием, который можно применять для синхронизации доступа к разделяемым ресурсам, предполагает использование ключевого слова lock
lock требует указания private void SomePrivateMethod()
{
// Использовать текущий объект как маркер потока.
lock(this)
{
// Весь код внутри этого блока является безопасным к потокам.
}
}
Тем не менее, если блокируется область кода внутри
object для применения в качестве маркера блокировки:public class Printer
{
// Маркер блокировки.
private object threadLock = new object();
public void PrintNumbers()
{
// Использовать маркер блокировки.
lock (threadLock)
{
...
}
}
}
В любом случае, если взглянуть на метод PrintNumbers()
Console внутрь области lock, как показано ниже:public void PrintNumbers()
{
// Использовать в качестве маркера блокировки закрытый член object.
lock (threadLock)
{
// Вывести информацию о потоке.
Console.WriteLine("-> {0} is executing PrintNumbers()",
Thread.CurrentThread.Name);
// Вывести числа.
Console.Write("Your numbers: ");
for (int i = 0; i < 10; i++)
{
Random r = new Random();
Thread.Sleep(1000 * r.Next(5));
Console.Write("{0}, ", i);
}
Console.WriteLine();
}
}
В итоге вы построили метод, который позволит текущему потоку завершить свою задачу. Как только поток входит в область lock
lock. Таким образом, если поток А получил маркер блокировки, то другие потоки не смогут войти А не освободит его.На заметку!
Если необходимо блокировать код в статическом методе, тогда следует просто объявить закрытую статическую переменную-член типаobject, которая и будет служить маркером блокировки.Запустив приложение, вы заметите, что каждый поток получил возможность выполнить свою работу до конца:
*****Synchronizing Threads *****
-> Worker thread #0 is executing PrintNumbers()
Your numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-> Worker thread #1 is executing PrintNumbers()
Your numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-> Worker thread #3 is executing PrintNumbers()
Your numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-> Worker thread #2 is executing PrintNumbers()
Your numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-> Worker thread #4 is executing PrintNumbers()