原理
quartz用的是行鎖,for update 是排他鎖,一旦獲取TRIGGER_ACCESS行鎖,這時(shí)候針對這行讀寫都不能進(jìn)行
session 1
set autocommit=0;
select * from QRTZ_LOCKS where lock_name = 'TRIGGER_ACCESS' for update ;
session2
session2將會(huì)被鎖住
select * from QRTZ_LOCKS where lock_name = 'TRIGGER_ACCESS' for update ;
//等待
代碼實(shí)現(xiàn)
自定義SemaPhore
public interface Semaphore {
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Interface.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/**
* Grants a lock on the identified resource to the calling thread (blocking
* until it is available).
*
* @param conn Database connection used to establish lock. Can be null if
* <code>{@link #requiresConnection()}</code> returns false.
*
* @return true if the lock was obtained.
*/
boolean obtainLock(Connection conn, String lockName) throws LockException;
/**
* Release the lock on the identified resource if it is held by the calling
* thread.
*/
void releaseLock(String lockName) throws LockException;
/**
* Whether this Semaphore implementation requires a database connection for
* its lock management operations.
*
* @see #obtainLock(Connection, String)
* @see #releaseLock(String)
*/
boolean requiresConnection();
}
實(shí)現(xiàn)者有DBSemaphore,SimpleSemaphore,JTANonClusteredSemaphore
obtainLock,是獲取鎖
對于DBSemaphore是獲取數(shù)據(jù)庫表的行的排它鎖.
public synchronized boolean obtainLock(Connection conn, String lockName) {
lockName = lockName.intern();
if(log.isDebugEnabled()) {
log.debug(
"Lock '" + lockName + "' is desired by: "
+ Thread.currentThread().getName());
}
if (!isLockOwner(lockName)) {
if(log.isDebugEnabled()) {
log.debug(
"Lock '" + lockName + "' is being obtained: "
+ Thread.currentThread().getName());
}
while (locks.contains(lockName)) {
try {
this.wait();
} catch (InterruptedException ie) {
if(log.isDebugEnabled()) {
log.debug(
"Lock '" + lockName + "' was not obtained by: "
+ Thread.currentThread().getName());
}
}
}
if(log.isDebugEnabled()) {
log.debug(
"Lock '" + lockName + "' given to: "
+ Thread.currentThread().getName());
}
getThreadLocks().add(lockName);
locks.add(lockName);
} else if(log.isDebugEnabled()) {
log.debug(
"Lock '" + lockName + "' already owned by: "
+ Thread.currentThread().getName()
+ " -- but not owner!",
new Exception("stack-trace of wrongful returner"));
}
return true;
}