Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Блокировка обращений к коллекции


Автор: novichiok 25.10.2011, 15:05
Здравствуйте.
    У меня такая проблема: В приложении множество потоков бегают случайный образом по MultiValueMap у которой в качестве value используется какой-то Collection. Эти потоки берут из Map'а коллекцию, извлекают из неё элемент,удаляют его из коллекции и обрабатывают. Если коллекция пустая то поток сабмитит таск на обновления коллекции для данного ключа в спец. пул. Этот пул содержит единственный поток, который и обновляет коллекции по ключу. Проблема заключается в том, что возможна такая ситуация когда несколько потоков достают по ключу одну и ту же коллекцию,она оказывается пустая, и сабмитят по сути один и тот-же таск на обновление. Я хочу этого избежать.Грубо говоря хотелось бы чтобы все выглядело так:
Код

Collection coll = myMap.getCollection(key);
if(coll.isLocked()) {
// Коллекция залочена, следовательно её не трогаем а переходим к коллекции для другого ключа

if(coll.isEmty()) {
coll.lock()// блокируем коллекцию чтобы никакой другой поток не мог к ней    
//обратиться, следовательно не мог получить для ней isEmpty() и засабмитить 
//таск на выполнение
pool.submit(new MyTask(coll));
}

Так будет происходить в потоках-обработчиках. А в потоке обновителе что-то в этом роде:
Код

...
//Обносвили коллекцию
coll.unLock(); // Сняли блокировку,теперь потоки обработчики снова могут обращаться к коллекции


Вопрос: как такой функционал реализовать правильно? (отнаследоваться от какой-то коллекции и сделать volatile флаг lock. как-то сильно просто) + Учитывая специфику задачи посоветуйте,пожалуйста, collection для мапа? Беря во внимание что из коллекции элементы нужно удалять, как-то не хочется использовать для таких целей ArrayList, из-за возможных тормозов с System.arrayCopy(...)

Автор: Stolzen 25.10.2011, 15:43
Думаю, что можно использовать ReentrantReadWriteLock, если я правильно все понял.

Автор: novichiok 25.10.2011, 16:19
Ну я тоже так думал. А затем нашел одну лазейку,из-за которой отказался отеё использования, а именно - у меня ведь главная цель не допустить сабмита одинаковых тасков в пул(тасков на обновление одной и той же коллекции), и вот предположим ситуацию :
- у меня *читающие* обращения к коллекции синхронизируются readLock'ом из readWriteLock()
- *пишущие* writeLock'ом.
Теперь предположим что 1 поток читает из очереди, обнаруживает что она пустая - сабмитит таск на выполенение, затем сразу же 2 поток опять читает из той же очереди и опять -она пустая, сабмитит таск на выполнение. Дело в том что есть *большая* вероятность того, что 2 поток-обработчик будет отрабатывать раньше чем *пишущий* таск из пула. ведь для того чтоб 2поток обработчик не смог даже читать из коллекции, для начала таск из пула должен начать в неё писать, тем самым залочив её даже на чтение. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)