Книга: Программирование на языке Ruby

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

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

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

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

Оглавление книги


Генерация: 1.120. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз