Попытка найти решение без блокировки для параллельной очереди C # - PullRequest
0 голосов
/ 27 июня 2019

У меня есть следующий код на C #: (_StoreQueue - это ConcurrentQueue)

        var S = _StoreQueue.FirstOrDefault(_ => _.TimeStamp == T);
        if (S == null)
        {
            lock (_QueueLock)
            {
                // try again
                S = _StoreQueue.FirstOrDefault(_ => _.TimeStamp == T);
                if (S == null)
                {
                    S = new Store(T);
                    _StoreQueue.Enqueue(S);
                }
            }
        }

Система собирает данные в режиме реального времени (довольно высокая частота, около 300-400 вызовов в секунду) и помещает ихв корзинах (объекты магазина), которые представляют 5-секундный интервал.Эти ячейки находятся в очереди по мере их записи, а очередь очищается по мере того, как данные обрабатываются и записываются.

Итак, когда поступают данные, выполняется проверка, чтобы проверить, есть ли ячейка для этой временной отметки (округляется на 5 секунд), если нет, то создается один.

Так как он довольно многопоточный, система использует следующую логику:

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

В этой системе блокировка примерно используется один раз каждые 2k вызовов

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

Альтернатива, о которой я думал, - это создание пустых корзин заранее, и это полностью удалило бынеобходимо для каких-либо блокировок, но поиск правой корзины будет медленнее, так как придется сканировать список предварительно созданных корзин, чтобы найти нужную.

1 Ответ

2 голосов
/ 27 июня 2019

Использование ConcurrentDictionary может исправить возникшую проблему.Здесь я предположил тип double для вашего свойства TimeStamp, но это может быть что угодно, если только ключ ConcurrentDictionary соответствует типу.

class Program
{
    ConcurrentDictionary<double, Store> _StoreQueue = new ConcurrentDictionary<double, Store>();

    static void Main(string[] args)
    {
        var T = 17d;

        // try to add if not exit the store with 17
        _StoreQueue.GetOrAdd(T, new Store(T));
    }
    public class Store
    {
        public double TimeStamp { get; set; }
        public Store(double timeStamp)
        {
            TimeStamp = timeStamp;
        }
    }
}
...