Clasp
Named reentrant locks with deadlock detection for Ruby
Installation & usage
Install using gem install clasp
or add it to your Gemfile
.
Basic usage
manager = Clasp::LockManager.new
manager.lock 'id1'
manager.unlock 'id1'
Deadlock detection
## Thread 1 ## Thread 2
manager.lock 'AAA' manager.lock 'BBB'
begin begin
manager.lock 'BBB' manager.lock 'AAA'
# do work... # do work...
manager.unlock 'BBB' manager.unlock 'AAA'
ensure ensure
manager.unlock 'AAA' manager.unlock 'BBB'
end end
Using standard locks, this program could run forever because of a deadlock. Using LockManager
prevents this by tracking all locks and checking if a deadlock is about to occur.
The first thread that detects the deadlock can release any locks it holds. After this happens, it can rollback and try again later. The competing thread will then be able to lock any resources it needs to continue.
Debugging deadlocks
Clasp provides advanced debugging information when deadlocks occur.
Turn on debugging mode for your application:
Clasp.debug = true
Then log the messages for Clasp::DeadlockError
. You could see informative details about how
the deadlock occured:
Imminent deadlock detected
#<Thread:0x62f0 id=6 run> wanted #<DisposableLock 25296/f2057ff3-1a65-4815-ac59-91d0d73f2c87>
#<Thread:0x62e4 id=7 sleep> is waiting on a lock owned by #<Thread:0x62f0 id=6 run>
Locks owned by #<Thread:0x62f0 id=6 run>
#<DisposableLock 25296/a8f0d33e-74db-45cd-867d-aa0ef82dfcf9>
Locks owned by #<Thread:0x62e4 id=7 sleep>
#<DisposableLock 25296/f2057ff3-1a65-4815-ac59-91d0d73f2c87>