Tengo el siguiente código en C #: (_StoreQueue es una concurrenteca)

        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);
                }
            }
        }

El sistema está recopilando datos en tiempo real (frecuencia bastante alta, alrededor de 300-400 llamadas / segundo) y lo pone en contenedores (almacene objetos) que representan un intervalo de 5 segundos. Estos contenedores están en una cola a medida que se escriben y la cola se vacía, ya que los datos se procesan y escriben.

Entonces, cuando lleguen los datos, se realiza un cheque para ver si hay un contenedor para esa marca de tiempo (redondeada por 5 segundos), si no, se crea uno.

Dado que esto es bastante roscado, el sistema va con la siguiente lógica:

Si hay un contenedor, se utiliza para poner datos. Si no hay ninguna papelera, se inicia un bloqueo y dentro de ese bloqueo, el cheque se realiza nuevamente para asegurarse de que no fue creado por otro hilo mientras tanto. Y si todavía no hay papel, se crea.

Con este sistema, la cerradura se usa aproximadamente una vez que cada 2K llama

Estoy tratando de ver si hay una manera de eliminar la cerradura, pero es principalmente porque estoy pensando que tiene que haber una solución mejor que el cheque doble.

Una alternativa en la que he estado pensando es crear contenedores vacíos antes de tiempo y eso eliminaría por completo la necesidad de cerraduras, pero la búsqueda de la bandeja correcta se volvería más lenta, ya que tendría que escanear las listas de contenedores pre-construidos para encontrar el adecuado

1
Thomas 27 jun. 2019 a las 20:44

1 respuesta

La mejor respuesta

El uso de un ConcurrentDictionary puede solucionar el problema que está teniendo. Aquí asumí un tipo doble para su propiedad TimeStamp, pero puede ser cualquier cosa, siempre que haga que la tecla ConcurrentDictionary coincida con el tipo.

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;
        }
    }
}
3
Franck 27 jun. 2019 a las 18:10