Изменить: использование MySQL...
Допустим, у вас есть приложение, которое добавляет учеников в класс, и в этом классе мало места... поэтому вы делаете что-то вроде этого:
def add
if some_classroom.size < MAX_SIZE
add_student_to_class
end
end
Это состояние гонки в многопоточной среде. Хромой.
Предполагая, что мы
- не хочу этого и
- не хотите блокировать нашу классную таблицу или запись (что приводит к тому, что наше приложение отстой в другом месте)
Что мы делаем?
Я предлагаю это:
class Classroom < ActiveRecord::Base
has_one :classroom_lock
after_create :create_lock_record
def create_lock_record
c = ClassroomLock.new
c.classroom = self
c.save!
end
end
class ClassroomLock < ActiveRecord::Base
belongs_to :classroom
end
def add
c = Classroom.first
ActiveRecord::Base.transaction do
c.classroom_lock.lock!
c = Classroom.first #load this again (it might have changed)
if c.size < MAX_SIZE
c.add_new_student(some_student)
else
do_stuff_about_not_enough_room
end
end
end
Кажется, это должно работать потрясающе. Мой (фиктивный) метод Classroom#show не блокируется, потому что запись класса на самом деле не заблокирована, а метод add фактически является однопоточным, поскольку любые дополнительные процессы будут вынуждены ждать блокировки! линии до тех пор, пока блокировка не будет снята.
Это работает? Может быть? Я думаю так? Я не знаю...
Я довольно много работал над этим с несколькими процессами одновременно, но трудно сказать наверняка (в конце концов, это состояние гонки).
Может ли кто-нибудь дать дополнительную информацию?