我尝试创建一个线程安全类,允许跟踪某些内容的扫描。我的班级是:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ScanInProgressTest {
@Test
public void testConcurrency() throws Exception {
// given
Integer scanId = 1;
int nbScans = 500_000;
ScanInProgress scanInProgress = new ScanInProgress(scanId, nbScans);
// when
for (int i = 1; i <= nbScans / 2; i++) {
new AddError(scanInProgress).start();
new AddSuccess(scanInProgress).start();
}
Thread.sleep(1000);
// then
assertEquals(nbScans, scanInProgress.getNbResponses());
assertEquals(nbScans / 2, scanInProgress.getNbSuccesses());
}
private class AddError extends Thread {
private ScanInProgress scanInProgress;
public AddError(ScanInProgress scanInProgress) {
this.scanInProgress = scanInProgress;
}
@Override
public void run() {
int before = scanInProgress.getNbResponses();
scanInProgress.addError();
int after = scanInProgress.getNbResponses();
assertTrue("Add error: before=" + before + ", after=" + after, before < after);
}
}
private class AddSuccess extends Thread {
private ScanInProgress scanInProgress;
public AddSuccess(ScanInProgress scanInProgress) {
this.scanInProgress = scanInProgress;
}
@Override
public void run() {
int beforeResponses = scanInProgress.getNbResponses();
int beforeSuccesses = scanInProgress.getNbSuccesses();
scanInProgress.addSuccess();
int afterResponses = scanInProgress.getNbResponses();
int afterSuccesses = scanInProgress.getNbSuccesses();
assertTrue("Add success responses: before=" + beforeResponses + ", after=" + afterResponses, beforeResponses < afterResponses);
assertTrue("Add success successes: before=" + beforeSuccesses + ", after=" + afterSuccesses, beforeSuccesses < afterSuccesses);
}
}
}
我有以下单元测试类:
Exception in thread "Thread-14723" java.lang.AssertionError: Add success successes: before=7362, after=7362
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.assertTrue(Assert.java:41)
当我运行测试时,我可以在日志中定期看到此错误:
scanInProgress.addSuccess()
断言让我想到当我调用方法scanInProgress.getNbSuccesses()
然后调用nbResponses.incrementAndGet()
时,第一个方法nbResponses.get()
中的指令尚未被确认,而第二个方法中的指令{{1返回一些东西。
我该怎么做才能纠正这个问题?
答案 0 :(得分:0)
据我解读这个问题,我认为你需要使用锁。在获取或设置变量之前,您需要获取锁定。这样,不能同时设置和读取变量。你得到类似下面的代码。
public final static Object LOCK = new Object();
private int yourvariable;
public void setVar(int var){
synchronized(LOCK){
yourvariable = var;
}
}
public int getVar(){
int toReturn;
synchronized(LOCK){
toReturn = yourvariable;
}
return toReturn;
}
注意:如果您的ScanInProgessClass是唯一的ScanInProgressClass类,则可以使用this
而不是LOCK对象。