Синхронизация потоков в операционной системе Windows, страница 3

Чтобы решить проблему, нужно каким-либо образом блокировать доступ к флагу других программ, в то время как одна из программ читает и тестирует его значение. Windows позволяет добиться этого несколькими разными способами. В частности, вы можете воспользоваться вызовом InterlockedIncrement. Однако это достаточно низкоуровневый вызов, и вам вряд ли придется часто его использовать. Интерфейс Win32 обладает более удобными средствами решения подобных проблем.

Чаще всего для обработки подобных ситуаций используется механизм под названием мьютекс (mutex, сокращение от mutual exclusion — взаимное исключение). Поток может получить мьютекс в собственное владение. При этом другие потоки не смогут завладеть мьютексом до тех пор, пока первый поток не освободит его. Таким образом, в любой момент времени мьютекс может принадлежать только одному потоку, что исключает конфликты между потоками.

Вариант 3

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

Для решения проблемы можно создать три мыотекса. Поток, желающий обратиться к серверу, обязан завладеть одним из мыотексов. Если ни одного свободного мыотекса не осталось, поток должен подождать. Более удобный cпocoб подразумевает использование семафоров, Семафор — это объект синхронизации содержащий в себе счетчик (с начальным значением, например, три). Каждый раз. когда поток использует семафор, значение счетчика уменьшается на единицу. Когда значение счетчика становится равным нулю, семафор становится недоступным для каких-либо потоков.

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

Еще немного о синхронизации

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

Работая в многозадачной рабочей среде, не стоит забывать о возможности возникновения взаимной блокировки потоков (deadlock). Представьте, что один поток собирается открыть файл А, а затем — файл В. В то же время другой поток намерен открыть файл В, а затем — файл А. Предположим, что первый поток только что открыл файл А, но при попытке открыть файл В он обнаруживает, что этот файл уже открыт вторым потоком. Первый поток переходит в режим ожидания, надеясь на то, что в скором времени файл В освободится. Однако в то же время второй поток, только что открывший файл В, обнаруживает, что файл А уже открыт первым потоком. Второй поток надеется, что в скором времени файл А освободится, и также переходит в режим ожидания. Таким образом, оба потока начинают ждать друг друга, и их выполнение останавливается.

Если ни один из двух потоков не освободит занятые им ресурсы (в нашем случае — файлы), оба они «подвиснут» и не смогут продолжить работу. Это и называется взаимной блокировкой потоков (deadlock). Существует множество способов решения проблемы. Например, можно организовать работу потока таким образом, чтобы он освобождал все занятые им ресурсы в случае, если он не может получить доступ к одному из необходимых ресурсов. Позже поток может повторить попытку получить доступ ко всем необходимым ресурсам. Для решения проблемы можно использовать мьютекс. В нашем достаточно простом примере можно организовать работу потоков таким образом, чтобы каждый из них прежде всего открывал файл А и лишь затем пытался открыть файл В. К сожалению, организовать работу программ именно таким образом удается далеко не всегда.