This depends on how locks are implemented. If you do it as in the Wikipedia article, i.e. guarding the critical section with one boolean per process¹, you are certainly in trouble. If one process dies, it never resets its flag so the other process loops forever.
In practice, you can safeguard your code against many ways of dying. For example, take this Java-style implementation:
flag[1] = true;
turn = 1;
while ( flag[0] == true && turn == 1 ) { Thread.yield(); }
try {
// critical section
}
finally {
flag[1] = false;
}
This will make sure the flag is reset whatever happens in the critical section, as long as the system is handling the error. In Java, that is true even for stack and heap overflows. So unless the process literally vanishes (kill
², processor failure, network disconnect, ...) you are safe. Note that most non-critical software fails in these cases -- how can it handle an error it it's not running? -- so that has to be accepted in many cases. You can handle inconsistencies upon restart if necessary.
If you use proper, language-level locks, the runtime system may handle vanishing lock owners, i.e. release locks with dead owners. You can simulate this yourself by giving each process a dead man's switch the others can read, or check directly whether the lock owning process is still alive (if the system supports it).
- That does not scale well, anyway.
- In Java, I think
finalize
should execute even on kill
, but this is not guarenteed by the spec. kill -9
is probably a death sentence for any solution that requires the dying process to do something.