2015-04-16 2 views
1

В someParameters HashMap загружается из CSV-файла через каждые двадцать минут или около одной нити и устанавливается SetParameters метода.поточно-перенастройки ссылки объекта

Это очень часто читается несколькими потоками, вызывающими getParameters: выполнить перевод перевода одного значения в соответствующее значение.

Является ли код небезопасным и/или «неправильным» способом достижения этого (особенно с точки зрения производительности)? Я знаю о ConcurrentHashMap, но я пытаюсь получить более фундаментальное понимание параллелизма, вместо того, чтобы использовать классы, которые по сути являются потокобезопасными.

Один потенциальный риск, который я вижу в том, что ссылка на объект someParameters может быть сброшен в то время как другой поток читает копию, так как другой поток не может иметь последние значения (которое не имело бы значения для меня).

public class ConfigObject { 
    private static HashMap<String, String> someParameters = new HashMap<String, String>(); 

    public HashMap<String, String> getParameters(){ 
     return new HashMap<String, String>(someParameters); 
     //to some thread which will only ever iterate or get 
    } 

    public void setParameters(HashMap<String, String> newParameters){ 
     //could be called by any thread at any time 
     someParameters = newParameters; 
    } 
} 
+0

создание совершенно нового хэшмапа для возврата из getParameters - действительно дорогое решение. Лучше всего было бы использовать Collections.unmodifiableMap – ControlAltDel

+0

Назначение - это атомный оператор, поэтому здесь нет проблем с потоком. – ControlAltDel

+0

@ControlAltDel Threading ** ** здесь проблема: все дело в видимости, а не в атомарности (в данном случае)! Поле должно быть опубликовано правильно, чтобы избежать условий гонки. – isnot2bad

ответ

2

Есть две проблемы

  1. проблемы видимости, поскольку someParameters после обновления не может быть виден другому потоку, чтобы исправить эту отметку someParameters в volatile.
  2. Другой проблемой является производительность одной из-за создания нового метода HashMap в методе get, чтобы исправить это использование метода Utility Collections.unmodifiableMap(), это просто обернуть исходную карту и запретить метод put/remove.
+0

У вас есть веская забота, но оригинальный плакат, не обновляющий исходную карту, он хочет каждый раз создавать новый файл csv, и в этом случае нет необходимости в потокобезопасной карте. –

+0

Вы правы. Вместо того, чтобы создавать новую карту для каждого запроса на получение, немодифицируемая карта является решением. Я думал, что вы хотите решить (параллельную) часть записи, непосредственно записывая исходную карту и возвращая немодифицируемую карту в методе get. Убрал мой комментарий. – isnot2bad

1

Если я правильно понимаю вашу проблему, вам необходимо изменить или заменить сразу несколько параметров (атомарно). К сожалению, ConcurrentHashMap не поддерживает вставки/обновления атомной массы.

Для этого вы должны использовать общие ReadWriteLock. Преимущество по сравнению с Collections.synchronized... состоит в том, что одновременно могут выполняться одновременно : если readLock приобретен из какого-либо потока, readLock().lock(), вызываемый из другого потока, не будет блокироваться.

ReadWriteLock lock = new ReadWriteLock(); 

// on write: 
lock.writeLock().lock(); 
try { 
    // write/update operation, 
    // e. g. clear map and write new values 
} finally { 
    lock.writeLock().unlock(); 
} 

// on read: 
lock.readLock().lock(); 
try { 
    // read operation 
} finally { 
    lock.readLock().unlock(); 
} 
+0

не будет этот блок 'get()' при выполнении записи? Я думаю, что создание новой карты и замена эталона лучше в этом случае с использованием летучих для безопасного опубликования. –

+0

@ kr.pradeep, конечно, будет, это цель записи блокировки. ОП попросил альтернативные решения, один из которых я представил. Проблема замены коллекции заключается в том, что другие потоки могут продолжать работать со старыми данными даже после обновления фактической коллекции. Я не знаю точно цели и ограничения OP: возможно, это допустимо, может быть, нет. –

+0

Не используйте эту сложную стратегию блокировки, если возможно простое поле 'synchronzed' или' volatile'! Мы не знаем, важна ли здесь производительность. Кроме того, я по-прежнему считаю параметр «ConcurrentHashMap» опцией, если нет инвариантов для нескольких записей карты. В этом случае нет необходимости иметь одно ядерное массовое обновление. – isnot2bad

Смежные вопросы