mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
Use double check pattern to avoid holding two locks in GlobalLock.java while trying to perserve intern semantic of global lock
This commit is contained in:
parent
4e10a97c87
commit
06b48945b1
@ -249,6 +249,7 @@ public class DbUtil {
|
||||
Connection conn = getConnectionForGlobalLocks(name, false);
|
||||
if(conn == null) {
|
||||
s_logger.error("Unable to acquire DB connection for global lock system");
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -67,18 +67,20 @@ public class GlobalLock {
|
||||
public int releaseRef() {
|
||||
int refCount;
|
||||
|
||||
synchronized(s_lockMap) { // // lock in sequence to prevent deadlock
|
||||
synchronized(this) {
|
||||
referenceCount--;
|
||||
refCount = referenceCount;
|
||||
|
||||
if(referenceCount < 0)
|
||||
s_logger.warn("Unmatched Global lock " + name + " reference usage detected, check your code!");
|
||||
|
||||
if(referenceCount == 0)
|
||||
releaseInternLock(name);
|
||||
}
|
||||
}
|
||||
boolean needToRemove = false;
|
||||
synchronized(this) {
|
||||
referenceCount--;
|
||||
refCount = referenceCount;
|
||||
|
||||
if(referenceCount < 0)
|
||||
s_logger.warn("Unmatched Global lock " + name + " reference usage detected, check your code!");
|
||||
|
||||
if(referenceCount == 0)
|
||||
needToRemove = true;
|
||||
}
|
||||
|
||||
if(needToRemove)
|
||||
releaseInternLock(name);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
@ -99,8 +101,12 @@ public class GlobalLock {
|
||||
}
|
||||
|
||||
private static void releaseInternLock(String name) {
|
||||
synchronized(s_lockMap) {
|
||||
s_lockMap.remove(name);
|
||||
synchronized(s_lockMap) {
|
||||
GlobalLock lock = s_lockMap.get(name);
|
||||
assert(lock != null);
|
||||
|
||||
if(lock.referenceCount == 0)
|
||||
s_lockMap.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,25 +141,29 @@ public class GlobalLock {
|
||||
return false;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
// we will discount the time that has been spent in previous waiting
|
||||
} else {
|
||||
// take ownership temporarily to prevent others enter into stage of acquiring DB lock
|
||||
ownerThread = Thread.currentThread();
|
||||
if(DbUtil.getGlobalLock(name, remainingMilliSeconds / 1000)) {
|
||||
lockCount++;
|
||||
holdingStartTick = System.currentTimeMillis();
|
||||
|
||||
// keep the lock in the intern map when we got the lock from database
|
||||
addRef();
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("lock " + name + " is acquired, lock count :" + lockCount);
|
||||
return true;
|
||||
} else {
|
||||
ownerThread = null;
|
||||
}
|
||||
return false;
|
||||
addRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(DbUtil.getGlobalLock(name, remainingMilliSeconds / 1000)) {
|
||||
synchronized(this) {
|
||||
lockCount++;
|
||||
holdingStartTick = System.currentTimeMillis();
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("lock " + name + " is acquired, lock count :" + lockCount);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
synchronized(this) {
|
||||
ownerThread = null;
|
||||
releaseRef();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if(interrupted) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user