Seguridad en el hilo basada en el valor del objeto -- # campo con multithreading campo con concurrency camp codereview Relacionados El problema

Thread-safety based on object value


2
vote

problema

Español

Necesito crear una seguridad de hilo en un método de API web, pero solo cuando dos solicitudes que contienen el mismo valor de propiedad se ejecutan simultáneamente.

He creado una mezcla de waithanderles y un concurrentedicto para mantener solo los hilos que tienen otro procesamiento de hilo un artículo similar.

¿Este código es seguro? El que me preocupa es el def GetACycle(start: String, maps: Map[String, List[String]]): (Boolean, List[String]) = { def explore(node: String, visits: List[String]): (Boolean, List[String]) = { if (visits.contains(node)) (true, (visits.+:(node)).reverse) else { if (maps(node).isEmpty) (false, List()) else { val id = maps(node).indexWhere(x => explore(x, visits.+:(node))._1) if (id.!=(-1)) explore(maps(node)(id), visits.+:(node)) else (false, List()) } } } explore(start, List()) } 0 con el def GetACycle(start: String, maps: Map[String, List[String]]): (Boolean, List[String]) = { def explore(node: String, visits: List[String]): (Boolean, List[String]) = { if (visits.contains(node)) (true, (visits.+:(node)).reverse) else { if (maps(node).isEmpty) (false, List()) else { val id = maps(node).indexWhere(x => explore(x, visits.+:(node))._1) if (id.!=(-1)) explore(maps(node)(id), visits.+:(node)) else (false, List()) } } } explore(start, List()) } 1 .

    def GetACycle(start: String, maps: Map[String, List[String]]): (Boolean, List[String]) = {     def explore(node: String, visits: List[String]): (Boolean, List[String]) = {       if (visits.contains(node)) (true, (visits.+:(node)).reverse)       else {         if (maps(node).isEmpty) (false, List())         else {           val id = maps(node).indexWhere(x => explore(x, visits.+:(node))._1)           if (id.!=(-1))             explore(maps(node)(id), visits.+:(node))           else             (false, List())         }       }     }     explore(start, List())   } 2  
Original en ingles

I need to create thread-safety on a Web-API method, but only when two requests containing the same property value are ran simultaneously.

I have created a mix of WaitHandles and a ConcurrentDictionary to only hold the threads that have another thread processing a similar item.

Is this code thread-safe? The one that worries me is the ContainsKey with the TryAdd.

 private readonly static ConcurrentDictionary _processingGateways = new ConcurrentDictionary();  public Models.Profile GetProfile([FromBody] GetProfileRequest request) {     if (!ModelState.IsValid)         throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, new HttpError(ModelState, true)));      if (_processingGateways.ContainsKey(request.GatewayId))         _processingGateways[request.GatewayId].WaitOne();     _processingGateways.TryAdd(request.GatewayId, new AutoResetEvent(false));      // Wait for this until prev with same gatewayId has finished     var device = _clientRegistrar.RegisterMobileEndpoint(Mapper.Map(request));      AutoResetEvent currentHandle;     _processingGateways.TryRemove(request.GatewayId, out currentHandle);     currentHandle.Set();      return Mapper.Map(device); }
        

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

Según msdn , todos miembros públicos y protegidos de ConcurrentDictionary<TKey, TValue> son shot-safe y se pueden usar simultáneamente de múltiples hilos . Sin embargo, la concurrencia solo se aplica a las acciones individuales realizadas en la instancia del ConcurrentDictionary . La situación no se ensuciará, si un hilo está realizando una operación string y otro hilo está realizando una operación lectura al mismo tiempo. pero , no hay protección dentro de la clase ConcurrentDictionary contra la situación, cuando se proporciona información del strong>, que tiene desde Cambiado y debido a eso, se realiza una operación no válida.

i no vea la razón de llamar termcap0 , dado que un Otro hilo podría eliminar ese elemento en particular entre el termcap1 < / Código> y el termcap2 Operaciones de accesorios de valor y termcap3 será lanzado.

  termcap4  

La tecla a su solución podría ser la termcap5 método. Va a bloquear el termcap6 para leer y devolver el elemento (si existe).

  termcap7  

(descargo de responsabilidad: el código utiliza variables C # 7.0)

Ahora estás asegurado contra la excepción.

Si inspecciona el código para las posibles situaciones de punto muerto, puede observar que es posible, que 99887776555443318 se ejecuta antes de termcap9 . Es bueno saberlo, que la espera regresa cuando se establecen todos los eventos y no importa, si ocurrió o no antes o no antes o después de que se llamara a la espera. Great , ¡no hay puntos muertos aquí!

 

According to MSDN, all public and protected members of ConcurrentDictionary<TKey,xe2x80x82TValue> are thread-safe and may be used concurrently from multiple threads. However, concurrency only applies to the individual actions performed on the instance of the ConcurrentDictionary. The situation will not get messy, if a thread is performing a write operation and an another thread is performing a read operation at the same time. But, there is no protection within the ConcurrentDictionary class against the situation, when an information of the past is provided, that has since changed and because of that, an invalid operation is performed.

I do not see the reason of calling ContainsKey, since an another thread could remove that particular element between the ContainsKey and the Dictionary value accessor operations and KeyNotFoundException will be thrown.

if (_processingGateways.ContainsKey(request.GatewayId)) // the element could be removed right at this point during execution     _processingGateways[request.GatewayId].WaitOne(); // KeyNotFoundException is thrown here _processingGateways.TryAdd(request.GatewayId, new AutoResetEvent(false)); 

The key to your solution could be the TryGetValue method. It is going to lock the ConcurrentDictionary for reading and return the element (if it exists).

if (_processingGateways.TryGetValue(request.GatewayId, out var Gateway))     Gateway.WaitOne(); _processingGateways.TryAdd(request.GatewayId, new AutoResetEvent(false)); 

(Disclaimer: code uses C#7.0 out variables)

Now your are secured against the exception.

If you inspect the code for possible deadlock situations, you might observe that it is possible, that Set gets executed before WaitOne. It is good to know, that the wait returns when all events are set and it does not matter, whether or not that happened before or after wait was called. Great, no deadlocks here!

 
 

Relacionados problema

6  Al leer simultáneamente un mapa, mientras que un solo hilo de fondo lo modifica regularmente  ( Concurrently reading a map while a single background thread regularly modifies i ) 
Tengo una clase en la que estoy poblando un mapa liveSocketsByDatacenter desde una sola hilo de fondo cada 30 segundos dentro 9988777665544334 y luego ten...

5  Herramienta para calcular el tiempo promedio que toma para una solicitud de tracción GitHub para fusionar  ( Tool to calculate the average time that takes for a github pull request to get m ) 
Estoy aprendiendo, y este es mi primer intento de una herramienta de línea de comandos que usa la API de GitHub para calcular el tiempo promedio que toma una ...

12  Entrevista de concurrencia  ( Concurrency interview ) 
Un poco de vuelta, tuve una entrevista donde plantearon un problema, en resumen: Mire un determinado directorio, y procese archivos JSON entrantes Estos ...

7  Descarga concurrente en Go  ( Concurrent download in go ) 
Escribí un programa para descargar archivos en manera concurrente / paralelo (gomaxprocs & gt; 1). Este es mi programa 2 nd (no juguete) escrito en Go. Po...

3  Implementando una fábrica segura de hilo con almacenamiento en caché  ( Implementing a thread safe factory with caching ) 
Tengo un 9988776655544330 que crea Connector Objetos basados ​​en parámetros como URL, nombre de usuario y contraseñas. El Connector2 El objeto implem...

4  Cola de tareas paralelas que se ejecuta en secuencia  ( Parallel task queue that runs in sequence ) 
Necesito una solución que ejecute solicitudes entrantes constantemente en una secuencia por recurso, pero paralela en general. El caso de uso: Muchos clie...

2  Método de actualización de bloqueo de reentrantreadwritelock  ( Reentrantreadwritelock lock upgrade method ) 
Tengo una pregunta sobre la actualización de bloqueo. Específicamente lo que me molesta está entre readlock.unlock () y siguiendo a writelock.lock () ... Esto...

3  Diseño de reutilización de la piscina de hilo con Ejecutors.NewFixedThreadPool en Java  ( Design of thread pool reuse with executors newfixedthreadpool in java ) 
En mi solicitud, tengo código que debería ejecutarse cada hora en un nuevo elemento y ejecutar una operación costosa con MultiPhreading: |2 Mis pregunt...

4  Pruebe una actualización especulativa, concurrente, libre de bloqueo y atómica hasta que las coincidencias de la condición de aburtar  ( Try a speculative concurrent lock free atomic update until abort condition ma ) 
Por favor, hágamelo saber si ve las mejoras de rendimiento, errores o cualquier cosa que cambie y por qué. public static bool TrySpeculativeUpdate(ref ...

3  SPSC espera un tampón de anillo libre para mensajes entrantes  ( Spsc wait free ring buffer for incoming messages ) 
Esto es para un solo productor y un solo tampón de anillo de espera libre de consumidores. Las escrituras necesitan ser esperadas por supuesto. Pre-asigna las...




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