2013-11-08 3 views
2

Im, использующий ConcurrentHashMap в многопоточной программе. Карта отображает ServerIDs на объекты, содержащие больше информации о сервере (независимо от того, онлайн-он или нет, сколько он использовался в последнее время и т. Д.). И ServerID, и ServerInformation неизменяемы.ConcurrentHashMap с неизменяемыми значениями - синхронизированная замена?

Чтобы обновить информацию о сервере я делаю более или менее то, что предлагается в качестве точки B) в этом вопросе: What is the preferred way to modify a value in ConcurrentHashMap?

а именно (измененная использовать свои собственные имена переменных) это:

public void addUsage(ServerID id, long moreUsage) { 
    ServerInfo oldInfo = serverMap.get(id); 
    ServerInfo newInfo = oldInfo.addUsage(moreUsage); 
    serverMap.put(id, newInfo); 
} 

Теперь мой вопрос: не следует ли синхронизировать этот метод, чтобы исключить возможность потери обновлений?

Или есть другой способ достичь этого? Возможно, что-то вроде следующего (отредактировано из моей первоначальной версии, чтобы удалить явную ошибку):

public void addUsage(ServerID id, long moreUsage) { 
    ServerInfo oldInfo = serverMap.get(id); 
    ServerInfo newInfo = oldInfo.addUsage(moreUsage); 
    while (!serverMap.replace(id, oldInfo, newInfo)) { 
     oldInfo = serverMap.get(id); 
     newInfo = oldInfo.addUsage(moreUsage); 
     // try again later 
     Thread.sleep(SOME_TIME); 
    }; 
} 
+1

'Thread.sleep' является неправильным ответом на неисправный' replace'; вместо этого вы должны переделать вычисление: redo 'serverMap.get (id)' и redo 'addUsage'. –

+0

Вы, конечно, правы! В противном случае замена, вероятно, никогда больше не сможет преуспеть ... Имеет ли смысл изменить мой вопрос, чтобы отразить ваше предложение? Извините, я новичок здесь ... –

ответ

2

Да, метод замены является правильным способом решения этой проблемы. Просто не забудьте переопределить равные значения на своих объектах значения соответствующим образом!

(Это предполагает вычисляет новое_значение относительно дешево и столкновение относительно редко. Если это интенсивный расчет и столкновения являются общими, это может быть целесообразно ввести семафор и сериализацию вычислений.)

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

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