Blocks when an incompatible lock is held by another process. A process may hold only one type of lock (shared or exclusive) on a file. When a process terminates in any way, the lock is released.
Assumes the file is unlocked.
TODO: integrate with async I/O