Как работать с блокировкой потока в C#?

Опубликовано: 8 Января, 2023

C# делает возможным параллельное выполнение кода с помощью потоков. Система пространства имен. Потоки, встроенные в C#, поддерживают использование потоков. Обычно мы создаем потоки для одновременного выполнения программы. Но в некоторых случаях мы можем не захотеть, чтобы наша программа выполнялась одновременно более чем одним потоком, т.е. мы хотим предотвратить одновременный доступ к ресурсу несколькими потоками. Ресурс здесь может относиться к типу данных или переменной, созданной в программе C#.

Заблокировать в С#:

Чтобы избежать описанного выше условия, C# имеет встроенное ключевое слово lock, которое предотвращает одновременный доступ к ресурсу двумя потоками. Синтаксис ключевого слова блокировки показан ниже:

Синтаксис:

lock(name_of_object) 
statements_to_be_executed_after_lock

Примечание. Важно использовать пространство имен System.Threading для реализации многопоточности и блокировки.

Работа С#:

Давайте посмотрим, как работает блокировка в C#:

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

Реализация блокировок будет объяснена на примере. Давайте сначала рассмотрим программу без использования блокировок.

Пример 1:

C#




using System;
// This namespace is necessary 
// to implement threading and
// locks
using System.Threading;
  
namespace No_Lock {
    public class no_lock {
      public static void Main(string[] args)
      {
          // Creating two threads on a code block func
          Thread a = new Thread(func);
          Thread b = new Thread(func);
          // Begin the execution of both threads using Start()
          a.Start();
          b.Start();
      }
  
      // This is the code block that is to be executed by
      // both the threads
      public static void func()
      {
          string str = "Hello World";
          for (int i = 0; i < str.Length; i++) {
              Console.Write(str[i]);
              Thread.Sleep(TimeSpan.FromSeconds(0.2));
          }
          Console.Write(" ");
      }
    }
}

Выход:

HHeelllloo  WWoorrlldd

Приведенная выше программа представляет собой простой код, в котором два потока выполняют функцию, выводящую символы строки. Как видно из вывода, второй поток начинает свое выполнение даже тогда, когда первый еще не завершил свое выполнение.

Теперь посмотрим на программу с использованием блокировок.

Пример 2:

C#




using System;
// This namespace is necessary 
// to implement threading and
// locks
using System.Threading;
  
namespace Locked_thread {
    public class locked_thread {
      // Creating an object that will 
      // be used to lock the thread
      public static readonly object locked = new object();
      // This is the code block that is
      // to be executed by
      // both the threads
      public static void func()
      {
          // This statement locks the thread 
          // when it begins execution
          lock(locked){
            string str = "Hello World";
            for (int i = 0; i < str.Length; i++) {
                Console.Write(str[i]);
            }
            Console.Write(" ");
          }
      }
        
      public static void Main(string[] args)
      {
          // Creating two threads on a code block func
          Thread a = new Thread(func);
          Thread b = new Thread(func);
          // Begin the execution of both
          // threads using Start()
          a.Start();
          b.Start();
      }
    }
}

Выход:

Hello World
Hello World

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