Como sblundy señaló, si todos los objetos son inmutables, de sólo lectura, no es necesario que preocuparse de bloqueo, sin embargo, esto significa puede tener que copiar objetos mucho. Por lo general, copiar utiliza malloc y malloc para bloquear las asignaciones de memoria entre subprocesos, por lo que los objetos inmutables pueden comprarle menos de lo que cree (malloc se escala bastante mal y malloc es lento; si realiza una gran cantidad de malloc en una sección de rendimiento crítico , no esperes buen rendimiento).
Cuando solo necesita actualizar variables simples (por ejemplo, 32 o 64 bit int o punteros), realizar simplemente operaciones de suma o resta en ellas o simplemente intercambiar los valores de dos variables, la mayoría de las plataformas ofrecen "operaciones atómicas" para eso (además, GCC ofrece estos también). Atomic no es lo mismo que thread-safe.Sin embargo, atomic se asegura de que si un subproceso escribe un valor de 64 bits en una ubicación de memoria, por ejemplo, y otro hilo lo lee, el de lectura obtiene el valor antes de la operación de escritura o después de la operación de escritura, pero nunca un roto. valor entre la operación de escritura (por ejemplo, una donde los primeros 32 bits ya son los nuevos, los últimos 32 bits siguen siendo el valor anterior! Esto puede suceder si no utiliza el acceso atómico en dicha variable).
Sin embargo, si tiene una estructura C con 3 valores, que desea actualizar, incluso si actualiza los tres con operaciones atómicas, estas son tres operaciones independientes, por lo tanto, un lector puede ver la estructura con un valor ya actualizado y dos no actualizados. Aquí, si necesita asegurarse, necesitará un candado; el lector verá que todos los valores de la estructura son antiguos o nuevos.
Una forma de hacer que los bloqueos se escalen mucho mejor es utilizando bloqueos R/W. En muchos casos, las actualizaciones de datos son bastante infrecuentes (operaciones de escritura), pero el acceso a los datos es muy frecuente (leer los datos), pensar en colecciones (hashtables, árboles). En ese caso, los bloqueos R/W le comprarán una gran ganancia de rendimiento, ya que muchos hilos pueden contener un bloqueo de lectura al mismo tiempo (no se bloquearán entre sí) y solo si un hilo desea un bloqueo de escritura, todos los otros hilos están bloqueados por el tiempo que se realiza la actualización.
La mejor manera de evitar problemas con el hilo es no compartir ningún dato entre los hilos. Si cada hilo trata la mayor parte del tiempo con datos a los que no tiene acceso ningún otro hilo, no necesitará en absoluto el bloqueo de esos datos (tampoco operaciones atómicas). Intente compartir la menor cantidad de datos posible entre los hilos. Entonces solo necesita una manera rápida de mover datos entre hilos si realmente tiene que hacerlo (ITC, Inter Thread Communication). Dependiendo de su sistema operativo, plataforma y lenguaje de programación (desafortunadamente no nos contó ninguno de estos), podrían existir varios métodos poderosos para ITC.
Y, por último, otro truco para trabajar con datos compartidos pero sin ningún bloqueo es asegurarse de que los subprocesos no accedan a las mismas partes de los datos compartidos. P.ej. si dos hilos comparten una matriz, pero uno solo tendrá acceso incluso, el otro solo índices impares, no necesitará bloqueo. O si ambos comparten el mismo bloque de memoria y uno solo usa la mitad superior, el otro solo el inferior, no necesita bloqueo. Aunque no se dice, esto conducirá a un buen rendimiento; especialmente no en CPU multinúcleo. Escribir operaciones de un subproceso en estos datos compartidos (ejecutar un núcleo) puede forzar el caché para que se vacíe otro subproceso (ejecutándose en otro núcleo) y estos flujos de caché son a menudo el cuello de botella para aplicaciones de múltiples subprocesos que se ejecutan en CPU multinúcleo modernas.
Creo que significa una estructura libre de bloqueo de hilo. –
¿Qué idioma estás usando? –