В памяти находится большая коллекция объектов типа R. Для изменения объекта требуется блокировка записи, а для чтения - блокировка чтения. Я мог бы сохранить ReadWriteLock как закрытый член класса R, однако я хочу сохранить память. В любой момент только небольшой процент объектов изменяется или читается. Есть несколько способов отказаться от сохранения блокировки чтения и записи для определенного ресурса (например, если он не читался или не записывался в течение некоторого времени, t). Для целей этого вопроса предположим, что периодически может определяться, что блокировка ресурса может быть удалена. Однако имейте в виду, что пока блокировка ресурса удаляется в потоке, один или несколько других потоков могут попытаться изменить или прочитать ресурс. Все это происходит в многопоточной среде. Как бы вы реализовали это с наименьшим количеством блокировок?
Например, один из способов сделать это - сохранить блокировки чтения и записи в параллельной карте:
Map<R,ReadWriteLock> map = new ConcurrentHashMap<>();
Когда определено, что блокировку чтения-записи для ресурса можно удалить, удалите ее с карты. Однако, как упоминалось выше, возможно, что после того, как было принято решение об удалении записи и до того, как запись будет удалена, другие потоки могут захотеть получить блокировку чтения или записи.
Вы можете подумать, что можно использовать комбинацию computeifabsent и remove. Однако это не работает. Например:
//--Thread1 write lock--
ReadWriteLock rwl = map.computeIfAbsent(r, r -> new ReadWriteLock()); // 1
rwl.writeLock.lock(); // 4
//Modify r here
//--Thread2: Removing entry--
map.remove(r); // 2
//Thread3: write lock
ReadWriteLock rwl = map.computeIfAbsent(r, r-> new ReadWriteLock()); // 3
rwl.writeLock.lock(); // 5
//Modify r here.
Проблема в том, что объект блокировки потоком 1 не будет таким же, как блокировка, полученная потоком 3 и неправильно разрешающая две записи одновременно. Цифры справа показывают порядок исполнения.
В ответе не обязательно использовать параллельную карту, как показано в приведенном выше примере, но это кажется хорошим началом и обеспечивает одновременный доступ к блокировкам. Если вы все же используете параллельную карту, не стесняйтесь обернуть ReadWriteLock в другую структуру или создать свою собственную версию ReadWriteLock.
Таким образом, вопрос заключается в том, как поддерживать блокировки чтения и записи для коллекции ресурсов без необходимости хранить блокировку чтения и записи для каждого объекта в коллекции и минимизировать конкуренцию за блокировку.
R
с карты дождитесь блокировки, пока она не уведомит. - person jaychang0917   schedule 04.09.2018