Это зависит от того, как реализованы блокировки. Если вы сделаете это, как в статье в Википедии, т.е. защитите критическую секцию с одним логическим значением на процесс¹, у вас наверняка возникнут проблемы. Если один процесс умирает, он никогда не сбрасывает свой флаг, поэтому другой процесс зацикливается навсегда.
На практике вы можете защитить свой код от многих способов смерти. Например, возьмем эту реализацию в стиле Java:
flag[1] = true;
turn = 1;
while ( flag[0] == true && turn == 1 ) { Thread.yield(); }
try {
// critical section
}
finally {
flag[1] = false;
}
Это гарантирует, что флаг сбрасывается, что бы ни происходило в критической секции, пока система обрабатывает ошибку. В Java это верно даже для переполнения стека и кучи. Поэтому, если процесс буквально не исчезнет ( kill
², сбой процессора, отключение сети, ...), вы в безопасности. Обратите внимание, что в большинстве случаев происходит сбой большинства некритического программного обеспечения - как оно может обработать ошибку, если оно не запущено? - так что это должно быть принято во многих случаях. При необходимости вы можете устранить несоответствия при перезагрузке.
Если вы используете правильные языковые блокировки, система времени выполнения может обрабатывать исчезающие владельцы блокировок, то есть снимать блокировки с мертвыми владельцами. Вы можете смоделировать это самостоятельно, предоставив каждому процессу переключатель мертвого человека, который могут прочесть другие, или непосредственно проверьте, активен ли процесс владения блокировкой (если система поддерживает его).
- В любом случае, это плохо масштабируется.
- В Java, я думаю,
finalize
должен выполняться даже на kill
, но это не гарантируется спецификацией. kill -9
Вероятно, это смертный приговор для любого решения, которое требует, чтобы процесс умирания что-то сделал.