如何同步两个并发的hibernate动作

时间:2016-05-18 18:10:04

标签: java multithreading hibernate oauth

所以,我有两个线程,每个都已经在他们自己的hibernate事务中(由于一些魔法,我无法控制)。他们都希望获得oauth连接,但令牌已过期,因此他们需要刷新并更新它。此特定提供程序在刷新时使旧访问令牌无效,因此所有线程必须最终使用最新的访问令牌。

我有一个分布式read-write locking mechanism(因为有多个应用程序实例),确保只有一个线程刷新oauth组件的标记,而其余的则等待获取更新的标记。 updateComponentgetComponent方法都在事务中创建自己的新事务,希望在write-lock发布之前进行刷新。不幸的是,情况似乎并非如此。

这是我的OauthComponent帮助

的界面
@Transactional(readOnly=false, rollbackFor=Throwable.class, propagation=Propagation.REQUIRES_NEW)
void updateToken(String connectionId, OauthComponentDto component);

@Transactional(readOnly=true, propagation=Propagation.REQUIRES_NEW)
<T extends OauthComponentDto> T getComponent(String connectionId);

这是我的oauth令牌刷新代码:

// FYI, already in a transaction here.  Can't change that
final String connectionId = connection.getIdentifier();
final String lockKey = String.format("%s-refresh", connectionId);

try {  // If write-lock can be acquired, refresh the token and save to db
    getWriteLock(lockKey);  
    try {
        Oauth2ComponentDto component = oauthComponentHelper.getOauthComponent(connectionId);
        if (isExpiringSoon(component)) {
            refreshToken(component, connection);
            oauthComponentHelper.updateToken(connectionId, component);  // updates in new transaction
        }
        return component;
    } finally {
        releaseWrite(lockKey);
    }
} catch (LockNotAcquiredException e) {
    try {  // Write-lock was not acquired, so wait for read-lock to get new token from db
        getReadLock(lockKey);
        try {
            Oauth2ComponentDto component = oauthComponentHelper.getOauthComponent(connectionId);  // gets with new transaction
            if (isExpiringSoon(component)) {
                throw new ExpiredAuthorizationException();
            }
            return component;
        } finally {
            releaseRead(lockKey);
        }
    } catch (LockNotAcquiredException e2) {
        throw new ExpiredAuthorizationException();
    }
}

最终发生的事情是等待读锁的线程最终使用旧的访问令牌。我相信这是因为读取线程在刷新更新之前最终从db读取。有没有人有任何建议?

0 个答案:

没有答案