Чтение онлайн

на главную - закладки

Жанры

Программирование на языке 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
, который приостанавливает поток на случайное время. Тем самым поведение программы становится недетерминированным и приближенным к реальности.

Листинг 13.1. Программа индексирования с ошибками (гонка)

@list = []

@list[0]="shoes ships\nsealing-wax"

@list[1]="cabbages kings"

@list[2]="quarks\nships\ncabbages"

def hesitate

 sleep rand(0)

end

@hash = {}

def process_list(listnum)

 lnum = 0

 @list[listnum].each do |line|

words = line.chomp.split

words.each do |w|

hesitate

if @hash[w]

hesitate

@hash[w] += ["#{listnum}:#{lnum}"]

else

hesitate

@hash[w] = ["#{listnum}:#{lnum}"]

end

end

lnum += 1

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

Защитник

Кораблев Родион
11. Другая сторона
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Защитник

Кодекс Императора V

Сапфир Олег
5. Кодекс Императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Императора V

Позывной "Князь" 2

Котляров Лев
2. Князь Эгерман
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Позывной Князь 2

Искатель 1

Шиленко Сергей
1. Валинор
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Искатель 1

Лекарь Империи 10

Карелин Сергей Витальевич
10. Лекарь Империи
Фантастика:
городское фэнтези
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Лекарь Империи 10

Лекарь Империи 9

Карелин Сергей Витальевич
9. Лекарь Империи
Фантастика:
городское фэнтези
аниме
боевая фантастика
5.00
рейтинг книги
Лекарь Империи 9

Великий род

Сай Ярослав
3. Медорфенов
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Великий род

Отморозок 1

Поповский Андрей Владимирович
1. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 1

Эммануэль

Арсан Эммануэль
1. Эммануэль
Любовные романы:
эро литература
7.38
рейтинг книги
Эммануэль

Изгой Проклятого Клана. Том 2

Пламенев Владимир
2. Изгой
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Изгой Проклятого Клана. Том 2

Последний наследник

Тарс Элиан
11. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний наследник

Младший сын

Балашов Дмитрий Михайлович
1. Государи московские
Научно-образовательная:
история
8.50
рейтинг книги
Младший сын

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

ЖЛ 8

Шелег Дмитрий Витальевич
8. Живой лед
Фантастика:
аниме
5.60
рейтинг книги
ЖЛ 8