Hi All,
I have implemented a locking method that in theory should work well, but it causes deadlock. The problem is that I know what is wrong but I am not quite sure how to fix it.
My locking code is:
public synchronized long lock(int recNo) throws RecordNotFoundException {
// Check if the database contains the specified record.
// If not throw a RecordNotFound exception.
// Check if the required record is already locked, If not locked, create
// lock for it.
// If locked, do this:
Object recordLock = lockedRecords.get(new Integer(recNo));
// Wait until the record is unlocked.
while (this.isLocked(recNo)) {
// Wait on the record lock itself, therefore the
thread // will only wake when the required lock is released, as
// oppose to waiting on the lock manager which would result
// in threads waking when any lock is released even if the
// lock they require is not released. This waistes CPU cycles.
synchronized (recordLock) {
try {
Thread.currentThread().yield();
recordLock.wait();
} catch (InterruptedException ie) {
log.warning("Caught: " + ie);
}
}
// Recheck that the required record still exists in the database as
// while any waiting, a previous thread may have deleted the record.
// If not in the database throw exception.
}
// Record is not locked, locking it.
lockedRecords.put(new Integer(recNo), new Long(cookie));
}
// Return lock cookie.
return cookie;
}
Basically, what I am doing is locking on the record lock itself, therefore when a record is unlocked it will call notifyAll on the lock, which will wake up all threads waiting only for that record. And not all threads waiting for other records, which would be the case if I called wait on the lock manager object.
The problem is that to wait on the lock itself, I need to synchronize on it. But the whole lock method istelf needs to be synchronized also as two threads cannot be locking at the same instant. When I wait on the lock, the locks 'lock' is released, but not that of the lock manager, which causes deadlock.
I do need to hold both locks, but I need a way release the lock manager's lock before I call wait on the lock itself, but am not sure who to do it.
Any help or comments are welcome...
Thanx,
James.