Как безопасно очистить буфер из другого потока без синхронизированных методов?

Есть несколько потоков, скажем B, C и D, каждый из которых записывает небольшие пакеты данных в буфер с высокой частотой. Они владеют своим буфером, и никто больше в него не пишет. Запись должна быть максимально быстрой, и я определил, что использование synchronized делает ее неприемлемо медленной.

Буферы представляют собой просто массивы байтов вместе с индексом первого свободного элемента:

byte[] buffer;
int index;

public void write(byte[] data) {
    // some checking that the buffer won't overflow... not important now
    System.arraycopy(data, 0, buffer, index, data.length);
    index += data.length;
}

Время от времени появляется поток A, чтобы сбрасывать буфер каждого в файл. Ничего страшного, если у этой части есть какие-то накладные расходы, поэтому использование synchronized здесь не проблема.

Теперь проблема в том, что какой-то другой поток может писать в буфер, в то время как поток A сбрасывает его. Это означает, что два потока пытаются выполнить запись в индекс примерно в одно и то же время. Это привело бы к повреждению данных, которое я хотел бы предотвратить, но без использования synchronized в методе write () .

У меня такое ощущение, что при правильном порядке операций и, возможно, некоторых volatile полях это должно быть возможно. Есть какие-нибудь яркие идеи?

6
задан Thomas 12 February 2011 в 09:22
поделиться