2016-11-02 2 views
1

У меня есть Java Потокобезопасная карту, которая хранит строки в объект отображения:Безопасна ли следующая реализация?

ConcurrentHashMap<String, MyObject> map = new ConcurrentHashMap<>(); 

Здесь MyObject является определенный пользователем класс. Теперь рассмотрим следующий метод:

public void replace(String key, MyObject o) { 
    MyObject m = map.get("somekey"); 
    synchronized(m) { 
     // Modify some internal components of m 
     // and some other objects related to m 
    } 
} 

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

public void put(String key, MyObject o) { 
    if (map.putIfAbsent(key, o) == null){ //do something 
    } 
    else { 
     replace(key, o); 
    } 
} 

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

+0

Это невозможно узнать без реализации «MyObject», и если можно получить доступ к этому конкретному экземпляру по-другому. Но простой ответ: возможно, нет. –

+0

@MarkRotteveel Я согласен, что мой вопрос был неполным. Теперь я добавил несколько подробностей. – Sohaib

+0

Я потерял 'replace' и' put' оба в вашем коде? –

ответ

3

Является ли следующая реализация потоком безопасной?

Это зависит от того, как получить доступ и изменять ваши экземпляры MyObject в вашем коде, если вы всегда получить доступ и изменить данный экземпляр MyObject в синхронизированный блок, используя этот MyObject экземпляр в качестве монитора объекта, то да будет нить безопасно, иначе этого не будет.


Ваш put метод не поточно, как putIfAbsent и replace не выполняются атомарно, которая может привести к гонки состояние выдает, использовать merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) чтобы сделать то же самое, но атомарно в следующем :

public void put(String key, MyObject o) { 
    map.merge(
     key, o, 
     (v1, v2) -> { 
      // Modify some internal components of v1 
      // and some other objects related to v1 
      return v2; 
     } 
    ); 
} 
+0

Да, для меня вопрос не в модификации myObject, а в том, что кто-то другой может пытаться работать на одном и том же ключе карты, заменив его другим экземпляром MyObject. – Sohaib

+0

проверить обновление моего ответа о методе put, это то, что вы хотели? –

+0

Да, но мне нужно обновить кое-что при записи. Я думаю, что правильный подход здесь был бы чем-то вроде этого ответа: http://stackoverflow.com/a/5640671/1901744 Это может сработать, хотя я считаю, что это не работает. – Sohaib

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