I have this JUnit test:
package com.baeldung.concurrent;
import static org.junit.Assert.assertEquals;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
/**
* This is defined as a manual test because it tries to simulate the race conditions
* in a concurrent program that is poorly designed and hence may fail nondeterministically.
* This will help the CI jobs to ignore these tests and a developer to run them manually.
*
*/
public class MyCounterSimpleManualTest {
@Test
public void testCounter() {
MyCounter counter = new MyCounter();
for (int i = 0; i < 500; i++)
counter.increment();
assertEquals(500, counter.getCount());
}
@Test
public void testCounterWithConcurrency() throws InterruptedException {
int numberOfThreads = 100;
ExecutorService service = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
MyCounter counter = new MyCounter();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
counter.increment();
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
@Test
public void testSummationWithConcurrencyAndWait() throws InterruptedException {
int numberOfThreads = 2;
ExecutorService service = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
MyCounter counter = new MyCounter();
for (int i = 0; i < numberOfThreads; i++) {
service.submit(() -> {
try {
counter.incrementWithWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
This is my MyCounter (version 1):
package com.baeldung.concurrent;
public class MyCounter {
private int count;
public void increment() {
int tmp = count;
count = tmp + 1;
}
public synchronized void incrementWithWait() throws InterruptedException {
int tmp = count;
wait(100);
count = tmp + 1;
}
public int getCount() {
return count;
}
}
Here is stacktrace with JUnit fail:
java.lang.AssertionError: expected:<2> but was:<1>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:647)
at org.junit.Assert.assertEquals(Assert.java:633)
at com.baeldung.concurrent.MyCounterSimpleManualTest.testSummationWithConcurrencyAndWait(MyCounterSimpleManualTest.java:60)
When I change MyCounter to this, JUnit works (version 2):
package com.baeldung.concurrent;
public class MyCounter {
private int count;
public void increment() {
count++;
}
public synchronized void incrementWithWait() throws InterruptedException {
wait(100);
count++;
}
public int getCount() {
return count;
}
}
Can someone explain me why first version of MyCounter doesnt work. Maybe there is some race condition issue but I dont understand why becouse method incrementWithWait() is synchronized.Thank you for help