我在Spring有一种情况,我将数据写入某些外部源, 现在在将数据写入外部源之前,
下面的代码大致解释了我是如何做到的。
//代码从这里开始
Lock lck = new ReentrantLock();
public void manipulateData(){
lck.lock();
//Object obj = read the data
//modify it
Write(obj)
lck.unlock();
}
// Code End here
现在在多线程环境中,当前发生的事情是在写入调用之后我正在调用unlock但是在我的函数执行完成之前我的事务没有提交。但是因为我打电话给解锁。其他线程获取锁并读取实际上正确的数据。
所以我希望锁定应该只在事务提交时由其他线程获取。
此外,我无法使用程序化交易。
答案 0 :(得分:0)
您可以考虑提取读取对象的代码并将其修改为不同的方法(使用@Transactional
注释)。然后应该在调用方法之前执行锁定,并在方法返回后释放。像这样:
@Autowired
private Dao dao;
public void manipulateData(){
lck.lock();
dao.update(myObj);
lck.unlock();
}
class Dao {
@Transactional
public void update(MyObject obj) {
//read and modify
}
}
答案 1 :(得分:0)
您可以实现类似于此的Aspect(AOP):
首先创建一个类似于此的专有Transactional:
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface LockingTransactional {
}
然后,方面的有趣代码应与此类似:
...
private final Lock lck = new ReentrantLock();
...
@Around("@annotation(<FULL-PACKAGE-NAME-HERE>.LockingTransactional)")
public Object intercept(ProceedingJoinPoint pjp) throws Throwable {
try {
lck.lock();
TransactionStatus status = createTransaction(); // create the transaction "manually"
Object result;
try {
result = pjp.proceed();
} catch (Throwable t) {
txManager.rollback(status);
throw t;
}
txManager.commit(status);
return result;
} finally {
lck.unlock();
}
}
...
private TransactionStatus createTransaction() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
def.setIsolationLevel(<YOUR-LEVEL-HERE>);
def.setPropagationBehavior(<YOUR-PROPAGATION-HERE>);
return txManager.getTransaction(definition);
}
...