Я не уверен, как вообще можно назвать этот поток безопасным, когда его просто нет.Вы не можете использовать простую переменную для обеспечения безопасности из-за условий гонки.Что происходит между проверкой того, что флаг равен нулю, и установкой его в единицу?Вы просто не знаете.Все может произойти и в конечном итоге произойдет в этот очень короткий промежуток времени, если вам не повезет.
То, что может произойти, - это выражение print
, заставляющее поток останавливаться достаточно долго, чтобы ваш сломанный механизм блокировки работал.При тестировании этого примера с использованием Ruby 1.9.2 он даже не заканчивается, печать точек кажется вечной.
Возможно, вы захотите попробовать переписать его, используя Mutex:
write_mutex = Mutex.new
read_mutex = Mutex.new
2000.times do
threads << Thread.new {
done_flag = false
while (!done_flag) do
print "." #### THIS LINE
write_mutex.synchronize do
read_mutex.synchronize do
add_to_file
done_flag = true
end
end
end
}
end
Этоправильный Ruby способ сделать синхронизацию потоков.Мьютекс не снимет блокировку, пока не будет уверен, что вы обладаете исключительным контролем над ним.Есть также метод try_lock
, который попытается захватить его и потерпит неудачу, если он уже занят.
Потоки могут доставлять массу неудобств, поэтому будьте очень осторожны при их использовании.