Ако имам несинхронизирана 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] Причините са голяма част от времето, прекарано в четене в сравнение с писане, съчетано с риска от въвеждане на блокирания.
Редактиране: Много добра информация в няколко от отговорите и коментарите, някои важни точки:
- В кода, който публикувах, имаше грешка. Синхронизирането на глобално (лошо наречена променлива) може да не успее да защити синхронизирания блок след размяна.
- Можете да коригирате това чрез синхронизиране на класа (преместване на ключовата дума synchronized към метода), но може да има други грешки. По-безопасно и по-поддържано решение е да използвате нещо от java.util.concurrent.
- Няма "евентуална гаранция за последователност" в кода, който публикувах, един от начините да се уверите, че читателите ще видят актуализациите от авторите, е да използвате ключовата дума volatile.
- Като се замисля, общият проблем, който мотивира този въпрос, беше опитът да се приложат lock free reads със заключени записи в java, но моят (решен) проблем беше с колекция, което може да бъде ненужно объркващо за бъдещите читатели. Така че, в случай че не е очевидно, кодът, който публикувах, работи, като позволява на един автор наведнъж да извършва редакции на „някакъв обект“, който се чете незащитен от множество нишки на четец. Ангажиментите на редакцията се извършват чрез атомарна операция, така че читателите могат да получат само „обекта“ преди или след редакцията. Когато/ако нишката на четеца получи актуализацията, това не може да се случи по средата на четене, тъй като четенето се извършва на старото копие на „обекта“. Просто решение, което вероятно е било открито и се е оказало неработещо по някакъв начин преди наличието на по-добра поддръжка на едновременност в java.
Unsafe
, трябва да е достатъчно голямо червено знаме, за да знаете, че могат да се случат лоши неща, ако го използвате! - person DaoWen   schedule 16.08.2012