Двухмерные изменчивые массивы: поможет ли самостоятельное назначение или мне нужен AtomicIntegerArray?

пишу аудио приложение DSP и яМы решили использовать модель производитель-потребитель. Я'много читал оvolatile и другие вопросы, связанные с потоками, но яУ меня есть пара вопросов о некоторых особенностях моего случая - в частности, одна из вещей, которую мне нужно разделить между потоками, - это массив массивов.

У меня есть класс, который представляет производителя. Чтобы учесть разницу во времени обработки, производитель хранитn буферы, которые будут заполняться по очереди каждый раз, когда будет доступно больше аудиоданных, и передавать буфер в поток потребителя.

начну с моих вопросов, а потомЯ постараюсь объяснить мою систему достаточно подробно - извините за длинный пост, спасибо за терпение со мной! Я'Буду также очень благодарен за общие комментарии о моей реализации и безопасности ее потоков.

Мои буферы представленыvolatile byte[][] массив. Я хорошо знаю, чтоvolatile только делаетссылка волатильно, но, прочитав SO и различные посты в блоге, кажется, у меня есть два варианта:

Я мог бы использоватьAtomicIntegerArray, Но:

Буду ли я ставить под угрозу производительность для такого приложения?

Атомность даже то, что мне нужно? Я намерен записать весь массив за один раз,затем Мне нужно, чтобы это было видно в другой теме, я некаждый нужениндивидуальный написать, чтобы быть атомным или видимым немедленно.

Если я правильно понимаю (например,этот блог), самостоятельное назначение, которое в моем случае:buffers[currentBuffer] = buffers[currentBuffer] обеспечит публикацию, которую вы увидите в моем коде ниже.

Это правильно, что это приведет к тому, что все последние записи станут видимыми?

Работает ли это в случае двумерного массива, как этот?

попробую кратко рассмотреть класс продюсера; это переменные экземпляра:

// The consumer - just an interface with a process(byte[]) method
AudioInputConsumer consumer;

// The audio data source
AudioSource source;

// The number of buffers
int bufferCount;

// Controls the main producer loop
volatile boolean isRunning = false;

// The actual buffers
volatile byte[][] buffers;

// The number of buffers left to process.
// Shared counter - the producer inrements and checks it has not run
// out of buffers, while the consumer decremenets when it processes a buffer
AtomicInteger buffersToProcess = new AtomicInteger(0);

// The producer thread.
Thread producerThread;

// The consumer thread.
Thread consumerThread;

Как только я начнуproducerThread а такжеconsumerThreadони просто выполняют методыproducerLoop а такжеconsumerLoop соответственно.

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

private void producerLoop() {
  int bufferSize = source.getBufferSize();
  int currentBuffer = 0;

  while (isRunning) {
    if (buffersToProcess.get() == bufferCount) {
      //This thread must be faster than the processing thread, we have run out
      // of buffers: decide what to do
      System.err.println("WARNING: run out of buffers");
    }

    source.read(buffers[currentBuffer], 0, bufferSize); // Read data into the buffer
    buffers[currentBuffer] = buffers[currentBuffer];    // Self-assignment to force publication (?)
    buffersToProcess.incrementAndGet();                 // Signal to the other thread that there is data to read
    currentBuffer = (currentBuffer + 1) % bufferCount;  // Next buffer
  }
}

consumerLoop ждет, покаAtomicInteger buffersToProcess больше нуля, затем вызывает потребительский объект, чтобы делать с данными все, что он хочет. потомbuffersToProcess уменьшается, и мы ждем, пока оно снова станет ненулевым.

private void consumerLoop() {
  int currentBuffer = 0;

  while (isRunning) {
    if (buffersToProcess.get() > 0) {
      consumer.process(buffers[currentBuffer]);          // Process the data
      buffersToProcess.decrementAndGet();                // Signal that we are done with this buffer
      currentBuffer = (currentBuffer + 1) % bufferCount; // Next buffer
    }
    Thread.yield();
  }
}

Большое спасибо!

Ответы на вопрос(3)

Ваш ответ на вопрос