Skip to content

Instantly share code, notes, and snippets.

@makasprzak
Created October 25, 2016 10:41
Show Gist options
  • Save makasprzak/46d9bd987e9476216a29633dc27f49e9 to your computer and use it in GitHub Desktop.
Save makasprzak/46d9bd987e9476216a29633dc27f49e9 to your computer and use it in GitHub Desktop.
thesis: toBuilder + copy of old state of e/l or journeys does not produce stale state
package com.goeuro.logic.search;
import com.jayway.awaitility.Awaitility;
import lombok.Builder;
import lombok.Data;
import lombok.Value;
import org.junit.Test;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class AtomicTest {
public static final int EXEC_TIMES = 10_000;
@Test
public void threadUnsafe() throws Exception {
AtomicReference<UnsafePojo> reference = new AtomicReference<>(new UnsafePojo());
AtomicInteger inconsistenciesCounter = new AtomicInteger(0);
AtomicInteger execCounter = new AtomicInteger(EXEC_TIMES);
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(() -> {
for (int i = 0; i < 1_000_000; i++) {
reference.getAndUpdate(ref -> {
ref.setX(ref.getX() + 1);
return ref;
}); //in single thread difference between x and y should never be
// greater then 1
reference.getAndUpdate(ref -> {
ref.setY(ref.getY() + 1);
return ref;
});
}
});
for (int i = 0; i < 10_000; i++) {
executorService.submit(() -> {
UnsafePojo ref = reference.get();
if (Math.abs(ref.getX() - ref.getY()) > 1)
inconsistenciesCounter.incrementAndGet();
execCounter.decrementAndGet();
});
}
Awaitility.await().atMost(5, TimeUnit.MINUTES).until(() -> execCounter.get() <= 0);
System.out.println("MUTABLE - Nr of inconsistencies detected: " + inconsistenciesCounter.get());
}
@Test
public void threadSafe() throws Exception {
AtomicReference<ImmutablePojo> reference = new AtomicReference<>(ImmutablePojo.builder().build());
AtomicInteger inconsistenciesCounter = new AtomicInteger(0);
AtomicInteger execCounter = new AtomicInteger(EXEC_TIMES);
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(() -> {
for (int i = 0; i < 1_000_000; i++) {
reference.getAndUpdate(ref -> ref.toBuilder().x(ref.getX() + 1).build()); //in single thread difference between x and y should never be
// greater then 1
reference.getAndUpdate(ref -> ref.toBuilder().y(ref.getY() + 1).build());
}
});
for (int i = 0; i < 10_000; i++) {
executorService.submit(() -> {
ImmutablePojo ref = reference.get();
if (Math.abs(ref.getX() - ref.getY()) > 1)
inconsistenciesCounter.incrementAndGet();
execCounter.decrementAndGet();
});
}
Awaitility.await().atMost(5, TimeUnit.MINUTES).until(() -> execCounter.get() <= 0);
System.out.println("IMMUTABLE - Nr of inconsistencies detected: " + inconsistenciesCounter.get());
}
}
@Value
@Builder(toBuilder = true)
class ImmutablePojo {
int x;
int y;
}
@Data
class UnsafePojo {
int x;
int y;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment