Нечастая запись и частое чтение

У меня есть следующая реализация JedisCluster, которую я хочу сделать потокобезопасной:

public class Cluster {
    private List<String> hostPorts;
    private Map<String, JedisPool> hostPool =
            new ConcurrentHashMap<String, JedisPool>();

    public add(String node) {
        hostPorts.add(node);
        hostPool.add(node, create_pool);
    } 

    public remove(String node) {
        hostPorts.remove(node);
        JedisPool pool = hostPool.remove(node)
        pool.destroy();
    }

    public String getMaster(String key) {
        return hostPorts.get(some_hash() % hostPool.size());
    }

    public JedisPool getPool(String node) {
        return redisHostPool.get(node);
    }

Ниже приведены темы -

  • 1 поток записи, который будет обновлять состояние при добавлении/удалении узла из кластера — это случается очень редко
  • 1 поток чтения, который будет часто читать вызовы getMaster() и getPool().

Я хочу знать лучшую стратегию для обработки описанного выше сценария с использованием параллелизма. Я хотел бы избежать синхронизации на уровне метода, так как чтение происходит очень часто.


person user1619355    schedule 15.06.2017    source источник
comment
Как правило, вы должны синхронизировать только _критические разделы кода, минимальный раздел кода, который обращается к общим данным. Вы не сказали нам, какие данные являются общими, но я предполагаю, что hostPorts и hostPool должно быть final. Если это так, все ваши тела методов getMaster, getPool и add должны быть синхронизированы на любом мониторе или блокировке, которые вы используете, а два вызова remove в методе remove должны быть вместе в синхронизированном блоке. (add и remove в вашем примере не скомпилируются.)   -  person Lew Bloch    schedule 16.06.2017


Ответы (1)


Используйте ReadWriteLock, что обычно означает ReentrantReadWriteLock:

ReadWriteLock поддерживает пару связанных блокировок, одну для операций только для чтения и одну для записи. Блокировка чтения может удерживаться одновременно несколькими потоками чтения, пока нет записывающих. Блокировка записи является монопольной.

person Andreas    schedule 15.06.2017
comment
даже если я использую writeLock внутри add/remove и readLock внутри getMaster/getPool, может возникнуть следующая ситуация, когда я не могу избежать повреждения: 1] читатель получает мастер 2] писатель удаляет узел (тот же, который читатель извлек ранее) 3] читатель вызывает getPool, передавая мастер, выбранный на шаге 1], который вернет null, поскольку он был удален на шаге 2] - person user1619355; 16.06.2017