2010-10-05 9 views
6

hasta el momento, pensé que cualquier operación realizada en el objeto "compartido" (común para múltiples hilos) debe ser protegida con "sincronizar", no importa qué. Aparentemente, estaba equivocado: en el código que estoy estudiando recientemente hay muchas clases (seguras para subprocesos, como afirma el autor) y solo una de ellas usa la sección crítica para casi todos los métodos.Enhebrado Delphi: ¿qué partes del código deben protegerse/sincronizarse?

¿Cómo puedo encontrar qué partes/métodos de mi código deben protegerse con CriticalSection (o cualquier otro método) y cuáles no?

Hasta ahora no he tropezado con ninguna explicación nota/artículo/blog interesante, todos los resultados de Google son:

a) Ejemplos de sincronización entre el hilo y la interfaz gráfica de usuario. Desde la barra de progreso simple hasta la más compleja, pero la lección es obvia: cada vez que accede/modifica la propiedad del componente de la GUI, haga eso en "Sincronizar". Pero nada más.

b) artículos que explican las Secciones críticas, Mutexes, etc. Solo unos enfoques diferentes de protección/sincronización.

c) Ejemplos de clases de seguridad de subprocesos muy simples (pila o lista de subprocesos) - todos hacen lo mismo - implementan métodos de bloqueo/desbloqueo que entran/salen de la sección crítica y devuelven el puntero de pila/lista real cierre.

Ahora estoy buscando la explicación qué partes del código deben protegerse.

podría ser en forma de código;) pero por favor no me dan uno más "usando Sincronizar para actualizar progressbar" ...;)

gracias!

Respuesta

5

Usted está solicitando respuestas específicas a una pregunta muy general.

Básicamente, aparte de las operaciones de la interfaz de usuario, se debe proteger a cada acceso de memoria/recurso compartido para evitar dos hilos potencialmente competidores a:

  • leer la memoria incompatible
  • escritura de la memoria al mismo tiempo
  • intento para usar el mismo recurso al mismo tiempo desde más de un hilo ... hasta que el recurso sea seguro para subprocesos.

Generalmente, considero seguro cualquier otro hilo de operación, incluidas las operaciones que acceden a la memoria no compartida o no comparten objetos.

Por ejemplo, considere este objeto:

type 
    TThrdExample = class 
    private 
    FValue: Integer; 
    public 
    procedure Inc; 
    procedure Dec; 
    function Value: Integer; 
    procedure ThreadInc; 
    procedure ThreadDec; 
    function ThreadValue: Integer; 
    end; 

ThreadVar 
    ThreadValue: Integer; 

Inc, dic y valor son métodos que operan sobre el campo FValue. Los métodos no son seguros para subprocesos hasta que los proteja con algún mecanismo de sincronización. Puede ser un MultipleReaderExclusiveWriterSinchronizer para la función Value y CriticalSection para los métodos Inc y Dec.

Los métodos ThreadInc y ThreadDec operan sobre la variable ThreadValue, que se define como ThreadVar, por lo que lo considero ThreadSafe porque la memoria a la que acceden no se comparte entre hilos ... cada llamada de un hilo diferente accederá a diferentes direcciones de memoria.

Si sabe que, por diseño, una clase debe usarse solo en un hilo o dentro de otros mecanismos de sincronización, puede considerar ese hilo seguro por diseño.

Si quiere respuestas más específicas, le sugiero que intente con una pregunta más específica.

Saludos cordiales.

EDIT: Tal vez alguien dice que los campos enteros es un mal ejemplo porque puede considerar operaciones enteras atómicas en Intel/Windows, por lo tanto no es necesario para protegerlo ... pero espero que entienda la idea.

+0

No quiero una respuesta más específica. De hecho, incluso estoy buscando más generales. Necesito aprender mucho acerca de cómo enhebrar, y estoy buscando un buen "punto de entrada";) Especialmente dado que estoy usando Delphi desde la versión 6 y NUNCA he visto la declaración de ThreadVar ... – migajek

+0

Por cierto, no debería ser el tercer punto ser "intentar NO usar ..."? ;) – migajek

+0

@migajek: No, el tercer punto es correcto. jachguate está diciendo qué dos hilos podrían estar haciendo que requerirían sincronización. –

2

Has malentendido el método TThread.Synchronize.

TThread.Synchronize y TThread.Queue methods ejecuta el código protegido en el contexto de la hebra principal (GUI). Es por eso que debe usar Syncronize o Queue para actualizar los controles de la GUI (como la barra de progreso); normalmente, solo el hilo principal debe acceder a los controles de la GUI.

secciones críticas son diferentes - el código protegido se ejecuta en el contexto del subproceso que adquirió sección crítica, y no se permite ningún otro hilo para adquirir la sección crítica hasta que los antiguos comunicados Roscarlo.

2

Utiliza la sección crítica en caso de que sea necesario actualizar un determinado conjunto de objetos atómicamente. Esto significa que, en todo momento, deben estar completamente actualizados o no actualizados en absoluto. Nunca deben ser accesibles en un estado de transición.

Por ejemplo, con un simple entero de lectura/escritura, este no es el caso. La operación de leer entero y la operación de escribirlo ya son atómicas: no se puede leer un entero en el medio del procesador que lo escribe, medio actualizado. Es un valor antiguo o nuevo, siempre.

Pero si quieres incremento el entero atómicamente, usted tiene no uno, sino tres operaciones que tiene que hacer a la vez: leer el valor antiguo en la memoria caché del procesador, se incrementará, y escribir de nuevo a la memoria. Cada operación es atómica, pero las tres juntas no lo son.

Un hilo puede leer el valor anterior (por ejemplo, 200), incrementarlo en 5 en caché, y al mismo tiempo, otro hilo también puede leer el valor (todavía 200). Luego, el primer hilo vuelve a escribir 205, mientras que el segundo hilo incrementa su valor en caché de 200 a 203 y escribe de nuevo 203, sobrescribiendo 205. El resultado de dos incrementos (+5 y +3) debe ser 208, pero es 203 por no -atomicidad de las operaciones.

Por lo tanto, se utiliza cuando las secciones críticas:

  1. Una variable, un conjunto de variables, o cualquier recurso se utiliza de varios hilos y necesita ser actualizado de forma atómica.
  2. No es atómica por sí mismo (por ejemplo, llamar a una función que está protegido por la sección crítica en el interior del cuerpo de la función, es una operación atómica ya)
1
+0

Este dominio parece haber pasado al lado oscuro y ahora es un portal para los sitios web del anunciante. Los tutoriales se pueden obtener en http://cc.embarcadero.com/Download.aspx?id=14809. Necesitará un inicio de sesión de CDN para descargar el archivo zip, que contiene la guía de subprocesamiento múltiple en formato HTML, junto con ejemplos de código. – rossmcm

0

Si usa mensajes para comunicarse entre hilos, básicamente puede ignorar completamente las primitivas de sincronización porque cada hilo solo accede a sus estructuras internas y a los mensajes. En esencia, esta es una arquitectura mucho más fácil y escalable que el uso de primitivas de sincronización.

Cuestiones relacionadas