Async lock

I've added tests, fixed a potential thread safe-issue and cleaned up a bit Async Lock.

Thread-safe issue (ecc2e6e3000dc68c5296374e40ea2c2b9d809379) could have manifested in a following situation:

first thread has acquired a lock and no work is available so it sets `@is_acquired=false`, mutex is ended, but before we could run `break unless @is_acquired` a second thread invokes wait on a lock therefore changing value of `@is_acquired`. Now first thread will pass the check but `work` variable is `nil` resulting in an exception.