Помогите с многопоточным кодом
От: vsb Казахстан  
Дата: 05.09.22 17:36
Оценка:
Функция должна возвращать два значения: 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);
                    }
                }
            }
        }
    }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.