Работы AtomicReferenceArray - PullRequest
       9

Работы AtomicReferenceArray

2 голосов
/ 04 февраля 2012

Мне интересно, можно ли использовать AtomicReferenceArray в качестве замены для ConcurrentLinkedQueue (если бы можно было жить с ограниченной структурой).

У меня сейчас есть что-то вроде:

ConcurrentLinkedQueue<Object[]> queue = new ConcurrentLinkedQueue<Object[]>();

public void store(Price price, Instrument instrument, Object[] formats){
     Object[] elements = {price, instrument, formats};
     queue.offer( elements);
}

Хранилище (..) вызывается несколькими потоками.

У меня также есть потребительский поток, который периодически просыпается и потребляет элементы.

private class Consumer implements Runnable{

@Override
public void run(){

List<Object[]> holder = drain( queue );
for(Object[] elements : holder ){
   for( Object e : elements ){
      //process ...
   }
}

private final List<Object[]> drain(){
//...
}

}

Можно ли поменять ConcurrentLinkedQueue на AtomicReferenceArray и при этом сохранить аспект безопасности потоков?

В частности, атомарное хранение элементов и установление отношения «происходит раньше», чтобы потребительский поток видел все элементы, хранящиеся в разных потоках?

Я попытался прочитать исходный код для AtomicReferenceArray, но все еще не совсем уверен.

Приветствия

Ответы [ 2 ]

1 голос
/ 04 февраля 2012

AtomicReferenceArray может использоваться в качестве безблокировочного кольцевого буфера для одного или нескольких производителей.Я экспериментировал с реализацией несколько месяцев назад и получил рабочий прототип.Преимущество заключается в уменьшении количества создаваемого мусора, лучшей локализации кэша и лучшей производительности, когда он не заполнен из-за упрощения.Недостатками являются отсутствие строгой семантики fifo и низкая производительность, когда буфер заполнен, так как производитель должен ждать, пока произойдет утечка.Это может быть смягчено путем возврата к ConcurrentLinkedQueue во избежание остановок.

Производители должны видеть преимущество перед событием, чтобы они получили уникальный слот.Однако, поскольку требуется только один потребитель, это может быть отложено до завершения слива.В моем случае сток амортизируется между потоками, поэтому потребитель выбирает успешное приобретение try-lock.Снятие этой блокировки обеспечивает преимущество, позволяя обновлениям массива использовать ленивые наборы в критической секции.

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

1 голос
/ 04 февраля 2012

Мне интересно, можно ли использовать AtomicReferenceArray в качестве замены для ConcurrentLinkedQueue (если можно жить с ограниченной структурой).

В принципе, нет.

Хотяотдельные обновления элементов массива происходят атомарно, что недостаточно для очереди.Вам также необходимо следить за тем, где находятся голова и хвост очереди, и вы не можете сделать это атомарно с помощью чтения / записи ячейки очереди, если не происходит какая-либо дополнительная блокировка / синхронизация.

(Этонезависимо от внутренней работы AtomicReferenceArray. Проблема заключается в том, что API не предоставит вам функциональность, необходимую для обновления двух вещей в одной атомарной операции.)

...