Следует ли синхронизировать очередь FIFO, если есть только один читатель и один писатель?
Синхронизация очереди FIFO
Ответы (5)
Что вы имеете в виду под «синхронизированным»? Если ваш читатель и писатель находятся в разных потоках, вы хотите, чтобы FIFO обрабатывал параллелизм «правильно», включая такие детали, как:
- правильное использование FIFO API никогда не должно приводить к повреждению структур данных
- правильное использование FIFO API не должно вызывать тупик (хотя должен быть механизм, позволяющий читателю ждать, пока будет что читать)
- объекты, считываемые из FIFO, должны быть теми же объектами, в том же порядке, записанными в FIFO (не должно быть пропущенных объектов или измененного порядка)
- должно быть ограниченное время (хотелось бы надеяться!) между тем, когда писатель помещает что-то в FIFO, и тем, когда это становится доступным для читателя.
В мире Java есть хорошая книга по этому поводу: Java Concurrency In Практика. Есть несколько способов реализовать FIFO, который правильно обрабатывает параллелизм. Самыми простыми реализациями являются блокирующие, в более сложных используются неблокирующие алгоритмы, основанные на инструкциях сравнения и замены, которые сегодня встречаются на большинстве процессоров.
Да, если читатель и писатель взаимодействуют с очередью FIFO из разных потоков.
В зависимости от реализации, но скорее всего. Вы не хотите, чтобы читатель читал частично записанные данные.
Да, если в документации явно не указано иное.
(Можно реализовать специализированный FIFO, который не требует синхронизации, если есть только один читатель и один поток записи, например, в Windows с использованием функций InterlockedXXX.)
Попробуйте этот код для одновременного использования FIFO:
public class MyObjectQueue {
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private static final ReadLock readLock;
private static final WriteLock writeLock;
private static final LinkedList<MyObject> objects;
static {
readLock = lock.readLock();
writeLock = lock.writeLock();
objects = new LinkedList<MyObject>();
}
public static boolean put(MyObject p) {
writeLock.lock();
try {
objects.push(p);
return objects.contains(p);
} finally {
writeLock.unlock();
}
}
public static boolean remove(MyObject p) {
writeLock.lock();
try {
return objects.remove(p);
} finally {
writeLock.unlock();
}
}
public static boolean contains(MyObject p) {
readLock.lock();
try {
return objects.contains(p);
} finally {
readLock.unlock();
}
}
public MyObject get() {
MyObject o = null;
writeLock.lock();
try {
o = objects.getLast();
} catch (NoSuchElementException nse) {
//list is empty
} finally {
writeLock.unlock();
}
return o;
}
}