Я использую WeakHashMap одновременно. Я хочу добиться мелкозернистой блокировки на основе параметра Integer; если поток A должен изменить ресурс, идентифицированный Integer a
, и поток B делает то же самое для ресурса, идентифицированного Integer b
, тогда их не нужно синхронизировать. Однако, если есть два потока, использующих один и тот же ресурс, скажем, что поток C также использует ресурс, идентифицированный Integer a
, тогда, конечно, потоки A и C необходимо синхронизировать с одним и тем же Блоком.Итерация WeakHashMap
Если нет потоков, которым нужен ресурс с идентификатором X, тогда блокировка на карте для ключа = X может быть удалена. Однако в этот момент может появиться другой поток и попытаться использовать блокировку в Map для ID = X, поэтому нам нужно глобальную синхронизацию при добавлении/удалении блокировки. (Это будет единственное место, где каждая нить должна синхронизироваться независимо от параметра Integer). Но нить не может знать, когда удалить блокировку, потому что она не знает, что это последний поток, использующий блокировку.
Вот почему я использую WeakHashMap: когда идентификатор больше не используется, пару ключ-значение можно удалить, когда GC хочет его.
Чтобы убедиться, что у меня есть сильная ссылка на ключ уже существующей записи, и именно эту ссылку на объект, который формирует ключ отображения, мне нужно итерируем Keyset карты:
synchronized (mrLocks){
// ... do other stuff
for (Integer entryKey : mrLocks.keySet()) {
if (entryKey.equals(id)) {
key = entryKey;
break;
}
}
// if key==null, no thread has a strong reference to the Integer
// key, so no thread is doing work on resource with id, so we can
// add a mapping (new Integer(id) => new ReentrantLock()) here as
// we are in a synchronized block. We must keep a strong reference
// to the newly created Integer, because otherwise the id-lock mapping
// may already have been removed by the time we start using it, and
// then other threads will not use the same Lock object for this
// resource
}
Теперь, может ли содержимое карты меняться при ее повторении? Я думаю, что нет, потому что, позвонив mrLocks.keySet()
, я создал сильную ссылку на все ключи для области итерации. Это верно?
См. Http://stackoverflow.com/questions/2861410/weakhashmap-iteration-and-garbage-collection – ikettu
Я думаю, что нет, из [JavaDoc] (http://docs.oracle.com/javase/7/ docs/api/java/util/WeakHashMap.html # keySet% 28% 29): * "** Набор поддерживается картой, поэтому изменения в карте отражаются в наборе и наоборот. **" * – m0skit0
@ m0skit0 Ах, возможно, вы правы. Возвращенный Set также содержит WeakReference, но он скрыт, как и WeakHashMap. Поэтому я должен сначала взять клон keySet, а затем перебрать клон, я думаю, чтобы убедиться, что я повторяю коллекцию с сильными ссылками. – Timmos