[英]Java unexpected concurrent result
在測試並發時,我發現了一些意想不到的事情。
使用 concurrentHashMap 和 AtomicLong 控制並發。
public class HumanRepository {
private final static Map<Long, Human> STORE = new ConcurrentHashMap<>();
private AtomicLong sequence = new AtomicLong();
public void save(Human human) {
STORE.put(sequence.incrementAndGet(), human);
}
public int size() {
return STORE.size();
}
public Long getSeq() {
return sequence.get();
}
}
我測試了多線程保存。
@Test
void name() throws NoSuchMethodException, InterruptedException {
final int threads = 3_500;
final ExecutorService es = Executors.newFixedThreadPool(threads);
final CountDownLatch count = new CountDownLatch(threads);
final HumanRepository repository = new HumanRepository();
for (int i = 0; i < threads; i++) {
try {
es.execute(() -> repository.save(new Human("aa")));
} finally {
count.countDown();
}
}
count.await();
System.out.println("seq = " + repository.getSeq());
System.out.println("size = " + repository.size());
}
我同時用 3500 個線程測試了它。 我預期的結果是 seq 和 size 都是 3500。
但有時我得到 seq=3499,size=3500。 這很奇怪。 很奇怪,seq出來的不是3500,雖然size是3500,seq是3499也沒意義。
不知道為什么map里面的data number和seq不一樣,3500出不來。
** 如果你做Thread.sleep(400L);
在count.await();
,奇怪的是,seq的值為3500
您實際上並不是在等待所有任務完成。 這意味着如果您獲得 3500/3500 output,那是偶然的。
具體來說,您在安排作業后減少主線程上的倒計時鎖存器,而不是在作業內部,一旦完成。 這意味着您的 countdownlatch 基本上只是另一個不進行任何線程間通信的美化循環變量。 試試這樣的事情:
for (int i = 0; i < threads; i++) {
es.execute(() -> {
repository.save(new Human("aa"));
count.countDown();
});
}
您在執行 HumanRepository.save() 的線程外調用 count.countDown()。 因此,主線程可能未同步完成線程。
因此,您可能會在一個線程運行時看到 repository.getSeq() 的結果。 您可以嘗試使用以下代碼嗎?
final int threads = 3_500;
final ExecutorService es = Executors.newFixedThreadPool(threads);
final CountDownLatch count = new CountDownLatch(threads);
final HumanRepository repository = new HumanRepository();
for (int i = 0; i < threads; i++) {
try {
es.execute(() -> {
repository.save(new Human("aa"));
count.countDown();
});
} finally {
}
}
count.await();
System.out.println("seq = " + repository.getSeq());
System.out.println("size = " + repository.size());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.