Я подумал: возможно ли иметь блокировку очереди, когда более одного темы читают или пишут? Я видел реализацию с заблокированной очередью, которая работала с одним прочитанным и одним потоком записи, но не более одного. Является ли это возможным? Я не думаю, что это так. Может ли кто-нибудь это доказать?Есть ли такая вещь, как блокированная очередь для нескольких потоков чтения или записи?
ответ
Есть несколько алгоритмов доступны, я в конечном итоге реализации An Optimistic Approach to Lock-Free FIFO Queues, что позволяет избежать проблем ABA через указатель пометки (нуждается в CMPXCHG8B
инструкции по x86
), и он прекрасно работает в приложении производства (написанном в Delphi). (Another version, with Java code)
Тем не менее, чтобы быть на самом деле, действительно беззамочные, вы также должны стопорное свободного распределения памяти - см Scalable Lock-Free Dynamic Memory Allocation (реализованный в Concurrent Building Block) или NBMalloc (но до сих пор я не получил использовать один из эти).
Вы также можете посмотреть ответы на optimistic lock-free FIFO queues impl?
Вам не нужна блокировка, а атомный способ удаления вещей из очереди. Это также возможно без блокировки и с атомной инструкцией test-and-set.
Является ли это одной команды процессора? – 2010-06-11 09:37:11
Инструкция по сборке CMPXCHG – Sjoerd
С .NET 4.0 существует ConcurrentQueue(T) Class.
В соответствии с C# 4.0 в двух словах, это реализация без блокировки. См. Также blog entry.
Существует динамическая блокировка свободная очередь в OmniThreadLibrary по Примозу Gabrijelcic (делфийская Geek): http://www.thedelphigeek.com/2010/02/omnithreadlibrary-105.html
реализация в Java из очереди беззамочной позволяет одновременно читает и пишет. Эта работа выполняется с помощью операции сравнения и установки (которая является одной инструкцией CPU).
В методе ConcurrentLinkedQueue
используется метод, при котором потоки помогают друг другу читать (или опросить) объекты из очереди. Поскольку он связан, глава очереди может принимать записи, в то время как хвост очереди может принимать чтения (при достаточном количестве места). Все это можно сделать параллельно и полностью безопасно для потоков.
С .NET 4.0 существует ConcurrentQueue Class.
Образец
https://dotnetfiddle.net/ehLZCm
public static void Main()
{
PopulateQueueParallel(new ConcurrentQueue<string>(), 500);
}
static void PopulateQueueParallel(ConcurrentQueue<string> queue, int queueSize)
{
Parallel.For(0, queueSize, (i) => queue.Enqueue(string.Format("my message {0}", i)));
Parallel.For(0, queueSize,
(i) =>
{
string message;
bool success = queue.TryDequeue(out message);
if (!success)
throw new Exception("Error!");
Console.WriteLine(message);
});
}
Я не понимал CAS, пока не прочитал инструкцию CMPXCHG. Инструкция CMPXCHG выглядит круто, поэтому я беру ее, если ее успех установит флаг Z? Теперь после минут путаницы с CAS до чтения CMPXCHG CAS выглядит как CAS (dst, oldValue, newVal); где dst - адрес, а два других - значения? если true, если dst была старой стоимостью и теперь заменена на newValue? (Я знаю, что много говорила, но думаю, что я прав, кажется, очень прав). – 2010-06-11 19:05:02
Знаете ли вы, есть ли существующие версии C++ 11 вашей статьи? Похоже, что это требует некоторой осторожности для реализации, и, хотя я действительно могу это использовать, я собираюсь пойти на реализацию блокировки, которую легче понять и проанализировать. – Omnifarious
Извините, бумага начинает становиться довольно стареющей, и я не искал никаких текущих реализаций, так как можно реализовать и отладить алгоритм на основе псевдокода. –