Могу ли я в Java зависеть от того, что присваивание ссылки является атомарным для реализации копирования при записи?

Если у меня есть несинхронизированная коллекция Java в многопоточной среде, и я не хочу заставлять читателей коллекции синхронизироваться[1] возможно ли решение, в котором я синхронизирую писатели и использую атомарность присваивания ссылок? Что-то вроде:

private Collection global = new HashSet(); // start threading after this

void allUpdatesGoThroughHere(Object exampleOperand) {
  // My hypothesis is that this prevents operations in the block being re-ordered
  synchronized(global) {
    Collection copy = new HashSet(global);
    copy.remove(exampleOperand);
    // Given my hypothesis, we should have a fully constructed object here. So a 
    // reader will either get the old or the new Collection, but never an 
    // inconsistent one.
    global = copy;    
  }
}

// Do multithreaded reads here. All reads are done through a reference copy like:
// Collection copy = global;
// for (Object elm: copy) {...
// so the global reference being updated half way through should have no impact 

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


[1] Причинами являются большая доля времени, затрачиваемого на чтение по сравнению с записью, в сочетании с риском возникновения взаимоблокировок.


Изменить :Много полезной информации в нескольких ответах и ​​комментариях, некоторые важные моменты:

  1. Ошибка присутствовала в коде, который я разместил. Синхронизация глобальной (переменной с неправильным именем )может не защитить синхронизированный блок после подкачки.
  2. Вы можете исправить это, синхронизируя класс (, переместив ключевое слово synchronized в метод ), но могут быть и другие ошибки. Более безопасное и удобное в сопровождении решение — использовать что-то из java.util.concurrent.
  3. В коде, который я разместил, нет «гарантии окончательной согласованности», один из способов убедиться, что читатели видят обновления авторов, - это использовать ключевое слово volatile.
  4. Поразмыслив, общая проблема, которая мотивировала этот вопрос, заключалась в попытке реализовать чтение без блокировки с блокировкой записи в java, однако моя (решенная )проблема была с коллекцией, что может излишне сбивать с толку будущих читателей. Поэтому, если это не очевидно, код, который я разместил, работает, позволяя одному писателю за раз вносить изменения в «некоторый объект», который читается незащищенным несколькими потоками чтения. Фиксация редактирования выполняется с помощью атомарной операции, поэтому читатели могут получить только «объект» до -редактирования или после -редактирования. Когда/если поток чтения получает обновление, оно не может произойти в середине чтения, так как чтение происходит в старой копии «объекта». Простое решение, которое, вероятно, было обнаружено и оказалось каким-то образом нарушенным до появления лучшей поддержки параллелизма в java.
8
задан MilesHampson 15 August 2012 в 08:49
поделиться