¿Es seguro confiar en el análisis estático para "reproducir" errores de concurrencia de manera confiable?


8

Heredé un código Java que sospecho que alberga algunos errores de concurrencia al sincronizar entre un hilo que consulta datos y un evento IO que actualiza los mismos datos. Estoy probando una herramienta de análisis estático llamada ThreadSafe que detecta varios problemas de concurrencia (es decir, campo al que se accede desde un método invocado asincrónicamente sin sincronización y sincronización inconsistente de accesos a una colección).

Después de descubrir lo difícil que es reproducir carreras de datos de manera confiable al escribir pruebas unitarias, me preguntaba si es aconsejable depender de ThreadSafe para "reproducir" los errores de manera confiable. Lo que pregunto es, ¿es seguro depender de la herramienta de análisis estático para decirme cuándo he corregido los errores? (Por supuesto, para corregir los errores tendré que entender cada uno en contexto).



66
En otras palabras, su pregunta es "¿el análisis estático tiene falsos negativos".

@delnan: EXTREMADAMENTE convincente, comentario perceptivo. +100 si pudiera.
John R. Strohm

Respuestas:


3

Respondiendo tu primera pregunta:

http://www.contemplateltd.com/threadsafe/faq#non-checkers

"¿Qué tipo de defectos de concurrencia no busca ThreadSafe?

  • Todavía no incluimos soporte para todo java.util.concurrent. Específicamente, ThreadSafe no verifica el uso indebido de las funciones de sincronización avanzadas proporcionadas por java.util.concurrent, por ejemplo, el paquete java.util.concurrent.atomic. Actualmente, tampoco incluye ningún verificador de errores que puedan ocurrir al escribir programas paralelos utilizando el marco de Fork-Join.

  • Encontrar errores en intrincados algoritmos sin bloqueo requiere una tecnología de análisis que no escala bien. Dichos algoritmos deben dejarse a expertos especializados en concurrencia. ThreadSafe se puede configurar para encontrar defectos en aplicaciones que usan bibliotecas que contienen dichos algoritmos.

  • Los análisis que incluimos en las nuevas versiones de ThreadSafe están dictados tanto por lo que es posible mediante el uso de tecnología de análisis lo suficientemente madura como para la integración en un producto utilizable, como por las características y defectos de concurrencia que vemos a menudo en los programas Java 'promedio'.

  • Si tiene un problema de concurrencia de Java que ThreadSafe no cubre actualmente, los especialistas en concurrencia de Java de Contemplate pueden ayudarlo agregando una configuración personalizada a ThreadSafe y / o mediante el uso de tecnología de análisis avanzada que aún no es lo suficientemente madura como para integrarse en ThreadSafe. "


1
Nota personal: RTFM! Esto responde a mi pregunta.
Doughgle 01 de

8

En mi experiencia, un desarrollador determinado, bien intencionado pero despistado puede envolver suficiente ofuscación en torno a un error de concurrencia que la herramienta de análisis lo perderá.

Si la herramienta cree que hay un error, suponga que es correcto hasta que demuestre lo contrario. Ese es el valor de la herramienta. Si la herramienta no encuentra ningún error, lo mejor es fingir que la herramienta no existe.

Si desea un código concurrente confiable (en cualquier idioma), sus objetivos deben incluir:

  1. Las secciones críticas deben ser pequeñas y simples para que sean triviales de entender.
  2. Las secciones críticas deben estar completamente aisladas de otro código a nivel fuente.
  3. Una función / método / subrutina involucrada en el código concurrente debe hacer una sola cosa . Si manipula una primitiva de sincronización (bloqueo, semáforo, etc.) NO debe jugar con ninguno de los recursos compartidos y NO debe contener bucles o código condicional. Mueva el "trabajo real" a una función separada. Esto es compatible con el elemento 1.
  4. Si tiene algún tipo de bloqueo, un desarrollador debería poder leer el código y determinar exactamente qué recurso (s) protege ese bloqueo en 30 segundos o menos. Si no es obvio para ti, no será obvio para el próximo tipo. Y probablemente no estaba claro para el tipo que escribió el código. Entonces probablemente esté roto.
  5. La visibilidad del recurso que está protegiendo no debe ser mayor que la visibilidad de la primitiva de sincronización que lo protege. Ninguno de los componentes debe ser visible para el cuerpo de código más grande.
  6. Etc. El resto de la lista es realmente una variedad de formas de replantear los elementos 1 y 2.

Si su código está diseñado y organizado correctamente, debería poder ver una pequeña fracción del código para comprender y confiar en la concurrencia. Al llegar a ese objetivo, entonces alimentar el código de la herramienta de análisis estático y ver si está de acuerdo.

Y entregue el código a algunos otros desarrolladores no gurú para su revisión. Pídales que expliquen cómo funciona la concurrencia y por qué es correcta. Si no pueden explicarlo, sigue siendo demasiado complejo.


2
algo que añadir a 4: cada recurso protegido por una cerradura se debe documentar que está protegido por la cerradura y nunca debe ser utilizado lejos de donde el bloqueo se accede
monstruo de trinquete

1
Algo que agregar: 6) NUNCA adquiera y mantenga más de un bloqueo en un instante dado. 7) Si absolutamente, DEBE adquirir y mantener más de una cerradura en un instante dado, asegúrese de que SIEMPRE se adquieran en el MISMO orden. Si el proceso A y el proceso B deben adquirir los bloqueos Rojo y Verde, pueden llegar a un punto muerto si uno de ellos adquiere Rojo primero y el otro adquiere Verde primero.
John R. Strohm

2

Producir una herramienta útil de análisis estático implica equilibrar una serie de preocupaciones conflictivas, que incluyen al menos las siguientes:

  • Tasa de falsos positivos (falsa alarma)
  • Tasa de falso negativo (error no detectado)
  • Tiempo de ejecución y escalabilidad

Los falsos positivos son una preocupación crítica con las herramientas de detección de errores, ya que pierden el tiempo del desarrollador. Es posible eliminar los falsos negativos, pero para muchos tipos de errores, incluidos los errores de concurrencia, esto implicaría un aumento inaceptable en la tasa de falsos positivos. La tasa de falsos positivos y falsos negativos se puede disminuir a costa de un mayor tiempo de ejecución, pero las técnicas de análisis más precisas no escalan más allá de las aplicaciones pequeñas, y de todos modos no se pueden reducir a cero.

Las herramientas de análisis dinámico a menudo reclaman una tasa de falsos positivos del 0%, pero eso se debe a que solo encuentran errores una vez que realmente ocurren. Para una condición de carrera o un punto muerto que solo ocurre una vez en una luna azul, eso no es tan útil.

Por estas razones, ThreadSafe no promete encontrar todos los errores de simultaneidad: su objetivo es encontrar los más importantes, con una baja tasa de falsos positivos. Algunos usuarios han probado ThreadSafe en código con un error de concurrencia conocido que tardaron días en encontrar, y descubren que encuentra ese error, y a menudo otros errores genuinos que no sabían, sin falsos positivos, en cuestión de minutos.

Un buen lugar para comenzar a obtener información sobre ThreadSafe es este artículo de InfoQ . Para obtener más información, visite el sitio web de ThreadSafe donde puede registrarse para obtener una prueba gratuita.

(Divulgación: ThreadSafe es una herramienta comercial, y soy cofundador de Contemplate, la compañía que lo produce).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.