Функция должна возвращать два значения: long x, int y. x это текущее время в миллисекундах. y это случайное число. Если вызывать функцию два раза подряд, то должно соблюдаться условие (x1, y1) < (x2, y2). Это, конечно, очевидно, если вызовы идут из одного потока. Если из двух потоков, то нужно, чтобы это условие сочеталось со стандартным java happens before (т.е. если потоки никак не связаны друг с другом, то как получится, если есть какие-то синхронизации между потоками, то должно условие соблюдаться). Ну и понятно, что оно должно работать как можно быстрей.
Я написал 3 версии функции. Первая очевидно правильная, но через sychronized, что слишком сильно для данных требований. Вторая и третья через volatile и atomic соответственно. Хочется понять, правильно ли я их написал и какой вариант лучше.
record Pair(long x, int y) {
}
private static final Random random = new Random();
private static long lastSynchronizedX;
private static int lastSynchronizedY;
static synchronized Pair synchronizedNext() {
while (true) {
int y = random.nextInt();
long x = System.currentTimeMillis();
if (x > lastSynchronizedX || y > lastSynchronizedY) {
lastSynchronizedX = x;
lastSynchronizedY = y;
return new Pair(x, y);
}
}
}
private static volatile long lastVolatileX;
private static volatile int lastVolatileY;
static Pair volatileNext() {
while (true) {
int y = random.nextInt();
long x = System.currentTimeMillis();
if (x > lastVolatileX || y > lastVolatileY) {
lastVolatileX = x;
lastVolatileY = y;
return new Pair(x, y);
}
}
}
private static final AtomicLong lastAtomicX = new AtomicLong();
private static final AtomicInteger lastAtomicY = new AtomicInteger();
static Pair atomicNext() {
while (true) {
long x = System.currentTimeMillis();
int y = random.nextInt();
long lx = lastAtomicX.get();
int ly = lastAtomicY.get();
if (x > lx || y > ly) {
if (lastAtomicX.compareAndSet(lx, x)) {
if (lastAtomicY.compareAndSet(ly, y)) {
return new Pair(x, y);
}
}
}
}
}