Вход/Регистрация
Программирование на языке Ruby
вернуться

Фултон Хэл

Шрифт:

t1 t2

– ------------------------- -----------------------------

Прочитать значение x (123)

Прочитать значение x (123)

Увеличить значение на 1 (124)

Увеличить значение на 1 (124)

Записать результат в x

Записать результат в x

Ясно, что каждый поток увеличивает на 1 то значение, которое видит. Но не менее ясно и то, что после увеличения на 1 обоими потоками

x
оказалось равно всего 124.

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

13.2.1. Синхронизация с помощью критических секций

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

Если акцессору

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

x = 0

t1 = Thread.new do

 1.upto(1000) do

Thread.critical = true

x = x + 1

Thread.critical = false

 end

end

t2 = Thread.new do

 1.upto(1000) do

Thread.critical = true

x = x + 1

Thread.critical = false

 end

end

t1.join

t2.join

puts x

Теперь последовательность выполнения изменилась; взгляните, в каком порядке работают потоки

t1
и
t2
. (Конечно, вне того участка, где происходит увеличение переменной, потоки могут чередоваться более-менее случайным образом.)

t1 t2

– ---------------------------- -----------------------------

Прочитать значение x (123)

Увеличить значение на 1 (124)

Записать результат в x

Прочитать значение x (124)

Увеличить значение на 1 (125)

Записать результат в x

Возможны такие комбинации операций с потоками, при которых поток планируется даже тогда, когда какой-то другой поток находится в критической секции.

Простейший случай — вновь созданный поток начинает исполнение немедленно вне зависимости от того, занимает какой-то другой поток критическую секцию или нет. Поэтому описанную технику лучше применять только в самых простых ситуациях.

13.2.2. Синхронизация доступа к ресурсам (mutex.rb)

В качестве примера рассмотрим задачу индексирования Web-сайтов. Мы извлекаем слова из многочисленных страниц в Сети и сохраняем их в хэше. Ключом является само слово, а значением — строка, идентифицирующая документ и номер строки в этом документе.

Постановка задачи и так достаточно груба. Но мы огрубим ее еще больше, введя следующие упрощающие допущения:

• будем представлять удаленные документы в виде строк;

• ограничимся всего тремя строками (они будут «зашиты» в код);

• сетевые задержки будем моделировать «засыпанием» на случайный промежуток времени.

Взгляните на программу в листинге 13.1. Она даже не печатает получаемые данные целиком, а выводит лишь счетчик слов (не уникальный). Каждый раз при чтении или обновлении хэша мы вызываем метод

hesitate
, который приостанавливает поток на случайное время. Тем самым поведение программы становится недетерминированным и приближенным к реальности.

  • Читать дальше
  • 1
  • ...
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: