Введение
Защищенный участок кода, который может выполняться не более чем одним процессом за раз.
В многопоточном программировании одновременный доступ к общим ресурсам может приводить к непредсказуемому или ошибочному поведению. Поэтому части программы, в которых осуществляется доступ к общим ресурсам, необходимо защищать способами, исключающими одновременный доступ. Один из таких способов известен как критическая секция или критическая область. В эту защищенную секцию одновременно может входить только один процесс или поток; остальные приостанавливаются до тех пор, пока первый не покинет критическую секцию. Как правило, критическая секция обращается к общим ресурсам, таким как структура данных, периферийное устройство или сетевое соединение, которые не будут функционировать корректно при множественном одновременном доступе.
In concurrent programming, concurrent accesses to shared resources can lead to unexpected or erroneous behavior. Thus, the parts of the program where the shared resource is accessed need to be protected in ways that avoid the concurrent access. One way to do so is known as a critical section or critical region. This protected section cannot be entered by more than one process or thread at a time; others are suspended until the first leaves the critical section. Typically, the critical section accesses a shared resource, such as a data structure, peripheral device, or network connection, that would not operate correctly in the context of multiple concurrent accesses.
Реализация критических разделов
Реализация критических секций различается в разных операционных системах. Критическая секция обычно завершается за конечное время, и поток, задача или процесс должны ожидать фиксированное время, чтобы войти в неё (ограниченное ожидание). Для обеспечения исключительного использования критических секций требуется некоторый механизм синхронизации при входе и выходе из программы. Критическая секция – это фрагмент программы, требующий взаимоисключающего доступа. Как показано на рисунке, в случае взаимоисключения (мьютекса) один поток блокирует критическую секцию, используя механизмы блокировки, когда ему необходимо получить доступ к общему ресурсу, а другие потоки должны ждать своей очереди для входа в секцию. Это предотвращает конфликты, когда два или более потоков совместно используют одно и то же адресное пространство и хотят получить доступ к общему ресурсу. После выхода из критической секции, и в некоторых случаях после завершения квант времени, будет выполнен ожидающее прерывание. Концепция кванта времени применима к планированию методом "round robin" и аналогичным политикам планирования. Поскольку критические секции могут выполняться только на процессоре, на котором они были вызваны, синхронизация требуется только в пределах этого процессора. Это позволяет входить и выходить из критических секций практически без затрат. Межпроцессорная синхронизация не требуется. Необходима только синхронизация потока инструкций. Большинство процессоров обеспечивают необходимый уровень синхронизации, прерывая текущее состояние выполнения. Это позволяет в большинстве случаев критическим секциям быть не более чем счётчиком вызовов критических секций для каждого процессора. Улучшения производительности включают выполнение ожидающих прерываний при выходе из всех критических секций и разрешение планировщику выполняться при выходе из всех критических секций. Кроме того, ожидающие прерывания могут быть переданы другим процессорам для выполнения. Критические секции не следует использовать в качестве длительного примитива блокировки. Критические секции должны быть достаточно короткими, чтобы их можно было войти, выполнить и выйти без каких-либо прерываний со стороны оборудования и планировщика. Критические секции ядра лежат в основе проблемы программной блокировки.
Критические разделы в структурах данных
При параллельном программировании код разделяется на потоки. Переменные, к которым осуществляется одновременное чтение и запись, распределяются между потоками, и каждый поток имеет свою копию этих переменных. Структуры данных, такие как связанные списки, деревья и хеш-таблицы, содержат связанные переменные данных, которые нельзя разделить между потоками, что значительно усложняет реализацию параллелизма. Для повышения эффективности реализации структур данных, такие операции, как вставка, удаление и поиск, могут выполняться параллельно. Однако в процессе выполнения этих операций могут возникать ситуации, когда один поток ищет элемент, а другой – удаляет его. В таких случаях результат может быть некорректным: поток, выполняющий поиск, может найти элемент, в то время как другой поток уже удалил его. Это приведет к ошибкам в работе программы и выдаче неверных данных. Чтобы избежать этого, одним из способов является защита всей структуры данных критической секцией, чтобы обеспечить последовательное выполнение операций. Другой способ – блокировка используемого узла в критической секции, чтобы другие операции не могли использовать тот же узел. Таким образом, использование критической секции гарантирует, что код выдает ожидаемые результаты.
Критические секции в отношении периферийных устройств
Критические секции также возникают в коде, который управляет внешними периферийными устройствами, такими как устройства ввода-вывода. Регистры периферийного устройства должны быть запрограммированы определенными значениями в определенной последовательности. Если два или более процесса одновременно пытаются управлять устройством, ни один из процессов не сможет привести устройство в требуемое состояние, что приведет к некорректной работе. Когда для формирования сложного блока информации на выходном устройстве требуется выполнение нескольких операций вывода, необходим исключительный доступ, чтобы другой процесс не повредил данные, вставляя свои собственные биты вывода. В направлении ввода исключительный доступ необходим при чтении сложного блока данных посредством нескольких отдельных операций ввода. Это предотвращает ситуацию, когда другой процесс может потребить часть данных, что приведет к их повреждению. Устройства хранения данных представляют собой форму памяти. Концепция критических секций в равной степени применима к устройствам хранения данных, как и к общим структурам данных в основной памяти. Процесс, выполняющий несколько операций доступа или обновления файла, выполняет критическую секцию, которую необходимо защитить соответствующим механизмом блокировки файла.