Mecanismo de cola seguro de hilo -- # campo con multithreading campo con thread-safety campo con queue camp codereview Relacionados El problema

Thread-safe queue mechanism


-1
vote

problema

Español

¿Es segura mi mecanismo de cola? Me pregunto si necesito colecciones concurrentes. ¿Necesito bloquear el método de enquema? La consola muestra la cuenta de cola en orden incorrecto, ¿afecta a MaxqueueCount en el método de carga? ¿Puedo mejorarlo de alguna manera?

  using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; using System.Timers;  class Program {     public class Document : IItem     {         public Guid Id { get; set; }     }      static void Main()     {         var queueProvider = new Provider();         var docs = new List<IItem>         {             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() }         };          try         {             var tasks = new List<Task>();              var task1 = Task.Factory.StartNew(() =>             {                 var timer1 = new Timer(1000) { Interval = 1000 };                 timer1.Elapsed += (object sender, ElapsedEventArgs e) =>                 {                     queueProvider.Load(docs, 1);                 };                 timer1.Enabled = true;                 timer1.Start();             });             tasks.Add(task1);              var task2 = Task.Factory.StartNew(() =>             {                 var timer1 = new Timer(1000) { Interval = 1000 };                 timer1.Elapsed += (object sender, ElapsedEventArgs e) =>                 {                     queueProvider.Load(docs, 2);                 };                 timer1.Enabled = true;                 timer1.Start();             });             tasks.Add(task2);              //Dequeue              //var task3 = Task.Factory.StartNew(() =>             //{             //    var timer1 = new Timer(3000) { Interval = 1000 };             //    timer1.Elapsed += (object sender, ElapsedEventArgs e) =>             //    {             //        queueProvider.Dequeue();             //    };             //    timer1.Enabled = true;             //    timer1.Start();             //});             //tasks.Add(task3);              Task.WaitAll(tasks.ToArray());         }         catch (Exception e)         {             Console.WriteLine(e);         }          Console.ReadKey();     } }   public interface IItem {     Guid Id { get; set; } }  public interface IProvider {     void Enqueue(IItem feedingItem, int id); }  public class Provider : IProvider {     private readonly ConcurrentQueue<IItem> queue;     private readonly ConcurrentDictionary<Guid, DateTime> inputBuffor;      private readonly object locker = new object();      private int maxQueueCount = 3;      public Provider()     {         queue = new ConcurrentQueue<IItem>();         inputBuffor = new ConcurrentDictionary<Guid, DateTime>();     }      public IItem Dequeue()     {         queue.TryDequeue(out var item);          Console.WriteLine("Dequeue: " + item.Id);          return item;     }      public void Enqueue(IItem item, int id)     {         //lock (locker)         //{         if (inputBuffor.TryAdd(item.Id, DateTime.Now))         {             queue.Enqueue(item);              Console.WriteLine("Enqueue: " + item.Id + "taskId: " + id);             Console.WriteLine("Count: " + queue.Count + " Buffor: " + inputBuffor.Count);         }         else         {             Console.WriteLine("Not Enqueue: " + item.Id + "taskId: " + id);         }         //}     }      public void Load(IEnumerable<IItem> data, int id)     {         foreach (var item in data)         {             if (queue.Count < maxQueueCount)                 Enqueue(item, id);         }     } }   
Original en ingles

Is it my queue mechanism thread safe? I just wonder if I need concurrent collections. Need I lock Enqueue method? Console displays queue count in incorrect order, Does it affect on maxQueueCount at Load method? Can I improve it in some way?

using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; using System.Timers;  class Program {     public class Document : IItem     {         public Guid Id { get; set; }     }      static void Main()     {         var queueProvider = new Provider();         var docs = new List<IItem>         {             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() },             new Document { Id = Guid.NewGuid() }         };          try         {             var tasks = new List<Task>();              var task1 = Task.Factory.StartNew(() =>             {                 var timer1 = new Timer(1000) { Interval = 1000 };                 timer1.Elapsed += (object sender, ElapsedEventArgs e) =>                 {                     queueProvider.Load(docs, 1);                 };                 timer1.Enabled = true;                 timer1.Start();             });             tasks.Add(task1);              var task2 = Task.Factory.StartNew(() =>             {                 var timer1 = new Timer(1000) { Interval = 1000 };                 timer1.Elapsed += (object sender, ElapsedEventArgs e) =>                 {                     queueProvider.Load(docs, 2);                 };                 timer1.Enabled = true;                 timer1.Start();             });             tasks.Add(task2);              //Dequeue              //var task3 = Task.Factory.StartNew(() =>             //{             //    var timer1 = new Timer(3000) { Interval = 1000 };             //    timer1.Elapsed += (object sender, ElapsedEventArgs e) =>             //    {             //        queueProvider.Dequeue();             //    };             //    timer1.Enabled = true;             //    timer1.Start();             //});             //tasks.Add(task3);              Task.WaitAll(tasks.ToArray());         }         catch (Exception e)         {             Console.WriteLine(e);         }          Console.ReadKey();     } }   public interface IItem {     Guid Id { get; set; } }  public interface IProvider {     void Enqueue(IItem feedingItem, int id); }  public class Provider : IProvider {     private readonly ConcurrentQueue<IItem> queue;     private readonly ConcurrentDictionary<Guid, DateTime> inputBuffor;      private readonly object locker = new object();      private int maxQueueCount = 3;      public Provider()     {         queue = new ConcurrentQueue<IItem>();         inputBuffor = new ConcurrentDictionary<Guid, DateTime>();     }      public IItem Dequeue()     {         queue.TryDequeue(out var item);          Console.WriteLine("Dequeue: " + item.Id);          return item;     }      public void Enqueue(IItem item, int id)     {         //lock (locker)         //{         if (inputBuffor.TryAdd(item.Id, DateTime.Now))         {             queue.Enqueue(item);              Console.WriteLine("Enqueue: " + item.Id + "taskId: " + id);             Console.WriteLine("Count: " + queue.Count + " Buffor: " + inputBuffor.Count);         }         else         {             Console.WriteLine("Not Enqueue: " + item.Id + "taskId: " + id);         }         //}     }      public void Load(IEnumerable<IItem> data, int id)     {         foreach (var item in data)         {             if (queue.Count < maxQueueCount)                 Enqueue(item, id);         }     } } 
           
         
         

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Para que desee una cola con un tamaño máximo, y no desea que el mismo artículo sea enquerado nuevamente.

Hay algunos problemas con el código:

  • Load no es seguro: no es evitando que otros hilos sean los elementos enqueurados después de la verificación de conteo de colas, por lo que es posible agregar más elementos de los permitidos.
  • Enqueue1 no comprueba el recuento de colas en absoluto, por lo que incluso es trivial agregar más artículos de lo permitido!
  • Load ignorada silenciosamente los artículos sin dejar que la persona que llama sepa. Incluso si devolvió la cantidad de artículos que realmente se agregaron, una persona que llama todavía no sabría cuáles. No creo que necesite este método en absoluto: una persona que llama puede hacer unir fácilmente algunos elementos y llame a Enqueue directamente.
  • Enqueue no dice si lo sucedió tampoco. Si un método puede fallar, entonces debería comunicarlo a sus personas que llaman (por ejemplo, nombrarlo TryEnqueue en su lugar, y al dejarlo devolver un booleano). También es una buena idea documentar su comportamiento.
  • Dequeue no verifica el valor de retorno de queue.TryDequeue . Eso causará un 9988777665544338 en la línea Console.WriteLine si la cola estaba vacía. Nuevamente, la documentación es una buena idea: ¿devuelve Enqueue0 si la cola está vacía, o si la persona que llama espera una excepción?
  • usando dos colecciones concurrentes internamente parece una exageración. Tampoco le ayudarán a hacer cumplir la restricción máxima de conteo, por lo que si eso es importante para usted, deberá usar algún tipo de bloqueo. Y si lo hace, también puede usar colecciones no concurrentes internamente, ya que las cerraduras se aseguran de que solo se acceda en un hilo a la vez.
 

So you want a queue with a maximum size, and you don't want the same item to be enqueued again.

There are a few problems with the code:

  • Load is not thread-safe: it's not preventing other threads from enqueuing items after the queue-count check, so it's possible to add more items than allowed.
  • Enqueue does not check the queue count at all, so it's even trivial to add more items than allowed!
  • Load silently ignored items without letting the caller know. Even if it returned how many items were actually added, a caller still wouldn't know which ones. I don't think you need this method at all: a caller can easily loop over some items and call Enqueue directly.
  • Enqueue doesn't tell whether it succeeded either. If a method can fail then it should communicate that to its callers (for example by naming it TryEnqueue instead, and by letting it return a boolean). It's also a good idea to document its behavior.
  • Dequeue does not check the return value of queue.TryDequeue. That will cause a NullReferenceException on the Console.WriteLine line if the queue was empty. Again, documentation is a good idea: does it return null if the queue is empty, or should the caller expect an exception?
  • Using two concurrent collections internally seems like overkill. They won't help you enforce the maximum count restriction either, so if that's important to you then you'll need to use some kind of locking. And if you do that, you might as well use non-concurrent collections internally, since the locks ensure that they're only accessed by one thread at a time.
 
 

Relacionados problema

2  Cola de bloqueo delimitada  ( Bounded blocking queue ) 
¿Puede alguien por favor revise este código para mí? No he implementado todos los métodos para la simplicidad. NSUSerDefaults1 Preguntas abiertas: l...

1  DEQUEUE () en la implementación de la cola que utiliza una lista circular vinculada  ( Dequeue in queue implememtation that uses a circular linked list ) 
Utilizo una lista de enlaces circulares para implementar un queue , y solo sostiene un 99887776665544332 (Tenga en cuenta que 99887776655443333 enlaces a...

2  Montón Binomial en Java  ( Binomial heap in java ) 
Tengo esta implementación de un montón de binomio que proporciona inserto, disminución de la tecla y el extracto en el tiempo logarítmico. minpriorityqueue...

8  Reader de cola sin bloqueo Seclador de Singler-Writer en C ++  ( Lockless queue multiple reader singler writer in c ) 
Escribí una cola sin encimera para enviar objetos pequeños desde un solo hilo a un hilo de trabajador aleatorio. suposiciones: x86 / x86_64 compilado con...

3  Cola MultiPhread Generic Simple  ( Simple generic multithreaded queue ) 
Esta es una cola de hilo simple que se usa en un modelo de consumidor productor. public class ThreadedQueue<TType> { private Queue<TType> _queue; p...

5  Cola de bloqueo con la exactitud de la lista doblemente vinculada  ( Lock free queue with doubly linked list correctness ) 
Necesito una cola de bloqueo que se implementa mediante la lista doblemente vinculada. es mi código correcto? ¿Hay algún error? ¿Hay alguna mejoras a realiz...

3  Cola de JavaScript para las funciones de ASYNC  ( Javascript queue for async functions ) 
Basado en la respuesta a Mi pregunta anterior sobre el desbordamiento de pila , armé la siguiente clase de cola. Me doy cuenta de que ya hay bibliotecas para...

4  Linkedlist para ser utilizado en una pila o cola  ( Linkedlist to be used in a stack or queue ) 
Todo esto funciona. Solo quería asegurarse de que no me perdí nada. Viniendo de C ++ y trabajando en mi camino a través de algoritmos, 4ta ed. Aquí está mi cl...

2  Implementación de la lista de la cola prioritaria  ( Priority queue linked list implementation ) 
Soy nuevo en Python y quería asegurarme de que mi código responde a la pregunta de mi tarea debido. Mi tarea: Una cola de prioridad es una cola en la que...

19  Una clase de hilo-piscina / cola personalizada  ( A custom thread pool queue class ) 
Quería una clase que ejecuta cualquier cantidad de tareas, pero solo cierta cantidad al mismo tiempo (por ejemplo, para descargar varios contenidos de Interne...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos