我在软件中发现了一个只在压力测试中发生的错误。如果呼叫同时或几乎同时发生,则调用大量函数并具有不同的行为。
我举了一个例子来说明发生了什么:
public void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
如果同时调用此功能两次,则只需支付一笔款项,即可完成两笔付款。
你有什么想法可以防止这种错误吗?
答案 0 :(得分:1)
您最简单的解决方案可能是同步它:
public synchronized void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
} else {
throw new MyException(myErrorCode);
}
}
这将确保任何时候只有一个线程可以在此对象中使用此方法。
这可能不是你想要的。例如,如果您有多个包含此方法的对象(可能在超类中),那么您应该使用不同的机制。
你应该学习并发和同步,以确保你做对了。众所周知,并发问题很难追查。
答案 1 :(得分:1)
您可以仅在帐户对象上进行同步,而不是在整个方法上进行同步。这样做会更好。这主要是因为我们不希望多个线程同时访问帐户对象。只要他们访问不同的帐户对象,他们就不应该互相阻止。
public void doPayment(Acccount account) throws MyException {
synchronized(account){
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
}
答案 2 :(得分:0)
使用同步
public void doPayment(Acccount account) throws MyException {
synchronized(key){
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
}
答案 3 :(得分:0)
我不是多线程计算方面的专家,但你必须考虑到这个调用有并发性。 基本上我认为你可以简单地这样做:
public synchronized void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
在不知道包含此方法的类的任何其他内容的情况下,这是我最好的答案。不同之处在于关键字“syncronized”允许java将“doPayment”调用为原子操作,因此没有人可以干涉。 有关同步的更好解释,请查看java reference about it。
最好的问候。