函数在压力测试下同时调用有不同的行为
Function has different behaviors in simultaneously calls under stress testing
我在一个软件中发现了一个只有在压力测试下才会出现的错误。如果同时或几乎同时调用,则函数被大量调用并且具有不同的行为。
我编了一个例子来说明正在发生的事情:
public void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
如果同时调用该函数两次,当账户有钱支付一次时,即完成两次支付。
你有什么办法可以防止这种错误吗?
您最简单的解决方案可能是同步它:
public synchronized void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
} else {
throw new MyException(myErrorCode);
}
}
这将确保任何时候只有一个线程可以使用此对象中的此方法。
这可能不是您想要的。例如,如果您有多个包含此方法的对象(可能在超类中),那么您应该使用不同的机制。
您应该学习并发和同步以确保您掌握了正确的知识。众所周知,并发问题很难追踪。
使用同步
public void doPayment(Acccount account) throws MyException {
synchronized(key){
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
}
我不是多线程计算方面的专家,但您必须考虑到您建议的此调用存在并发性。
基本上我认为你可以简单地这样做:
public synchronized void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
在不知道包含此方法的 class 的任何其他内容的情况下,这是我的最佳答案。不同之处在于关键字 "syncronized" 允许 java 将 "doPayment" 调用作为原子操作,因此没有人可以干涉。
有关同步的更好解释,请查看 java reference about it.
此致。
您可以只在帐户对象上同步,而不是在整个方法上同步。这样它会表现得更好。这本质上是因为我们不希望多个线程同时访问帐户对象。只要他们正在访问不同的帐户对象,他们就不应该互相阻止。
public void doPayment(Acccount account) throws MyException {
synchronized(account){
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
}
我在一个软件中发现了一个只有在压力测试下才会出现的错误。如果同时或几乎同时调用,则函数被大量调用并且具有不同的行为。
我编了一个例子来说明正在发生的事情:
public void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
如果同时调用该函数两次,当账户有钱支付一次时,即完成两次支付。
你有什么办法可以防止这种错误吗?
您最简单的解决方案可能是同步它:
public synchronized void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
} else {
throw new MyException(myErrorCode);
}
}
这将确保任何时候只有一个线程可以使用此对象中的此方法。
这可能不是您想要的。例如,如果您有多个包含此方法的对象(可能在超类中),那么您应该使用不同的机制。
您应该学习并发和同步以确保您掌握了正确的知识。众所周知,并发问题很难追踪。
使用同步
public void doPayment(Acccount account) throws MyException {
synchronized(key){
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
}
我不是多线程计算方面的专家,但您必须考虑到您建议的此调用存在并发性。 基本上我认为你可以简单地这样做:
public synchronized void doPayment(Acccount account) throws MyException {
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
在不知道包含此方法的 class 的任何其他内容的情况下,这是我的最佳答案。不同之处在于关键字 "syncronized" 允许 java 将 "doPayment" 调用作为原子操作,因此没有人可以干涉。 有关同步的更好解释,请查看 java reference about it.
此致。
您可以只在帐户对象上同步,而不是在整个方法上同步。这样它会表现得更好。这本质上是因为我们不希望多个线程同时访问帐户对象。只要他们正在访问不同的帐户对象,他们就不应该互相阻止。
public void doPayment(Acccount account) throws MyException {
synchronized(account){
if (isMoneyAvailable(account)) {
confirmPayment(account);
}else{
throw new MyException(myErrorCode);
}
}
}