"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Subprocesos múltiples: conceptos clave para ingenieros - Parte 1

Subprocesos múltiples: conceptos clave para ingenieros - Parte 1

Publicado el 2024-11-08
Navegar:758

Multithreading : Key Concepts for Engineers - Part 1

Comprender los conceptos clave de subprocesos múltiples es crucial para los desarrolladores de software, ya que no solo mejora el conjunto de habilidades sino que también afecta directamente el desarrollo de aplicaciones, la escalabilidad y la calidad general de las soluciones de software.

Atomicidad

En el contexto de subprocesos múltiples, las operaciones atómicas garantizan que un subproceso pueda ejecutar una serie de acciones sin la interrupción de otros subprocesos. Varios subprocesos pueden intentar leer o escribir datos compartidos simultáneamente. Sin atomicidad, las modificaciones simultáneas pueden generar resultados inconsistentes o inesperados, comúnmente conocidos como condiciones de carrera.

La especificación Java garantiza que 'lectura' y 'escritura' son operaciones atómicas, no sus combinaciones. por lo que una operación que "lee, suma 1 y luego escribe el resultado" no es atómica según la especificación. Estas operaciones se denominan operaciones compuestas y, por lo general, deben ser atómicas en el contexto de su uso en nuestro código.

Ejemplos de operaciones atómicas:

  1. Incrementar un contador: si dos subprocesos incrementan un contador al mismo tiempo sin atomicidad, ambos pueden leer el mismo valor y volver a escribir el mismo valor incrementado, lo que lleva a una pérdida de uno. incremento.

  2. Actualización de una variable compartida: Si un hilo lee un valor mientras otro lo modifica, sin atomicidad, el hilo de lectura puede obtener un valor inconsistente.

Lograr la atomicidad:

  • Clases atómicas: muchos lenguajes de programación proporcionan clases atómicas (por ejemplo, AtomicInteger en Java) que encapsulan operaciones que se garantiza que son atómicas.

  • Métodos/Bloques sincronizados: en lenguajes como Java, puedes usar la palabra clave sincronizada para asegurar que solo un hilo pueda ejecutar un bloque de código o un método a la vez.

  • Bloqueos: uso de bloqueos explícitos (por ejemplo, ReentrantLockin Java) para gestionar el acceso a recursos compartidos.

Beneficios

  • Rendimiento: Las clases en java.util.concurrent.atomic también proporcionan un enfoque sin bloqueos para garantizar la seguridad de los subprocesos, lo que las convierte en la opción preferida en muchos escenarios.
  • Simplicidad: El uso de clases atómicas simplifica el código, ya que los desarrolladores no necesitan administrar bloqueos y pueden centrarse en la lógica del programa.
  • Seguridad de subprocesos: Las operaciones atómicas garantizan que las variables se actualicen de forma segura en múltiples subprocesos sin riesgo de corrupción de datos o condiciones de carrera.

Inmutabilidad

La inmutabilidad se refiere a la propiedad de un objeto cuyo estado no se puede modificar después de su creación. En programación, los objetos inmutables son aquellos que, una vez inicializados, no se pueden cambiar ni alterar. En lugar de modificar un objeto inmutable, se crea un nuevo objeto con los cambios deseados.

Inmutable significa que una vez que el constructor de un objeto ha completado la ejecución, esa instancia no se puede modificar.

Características de los objetos inmutables

  • Sin cambio de estado: Una vez que se crea un objeto inmutable, su estado (atributos o campos) permanece constante durante toda su vida.

  • Apto para subprocesos: Los objetos inmutables se pueden compartir de forma segura entre varios subprocesos sin necesidad de sincronización, ya que no se pueden modificar.

  • Estabilidad del código hash: El código hash de un objeto inmutable permanece igual durante toda su vida, lo que lo hace adecuado para su uso en colecciones basadas en hash como HashMap o HashSet.

Lograr la inmutabilidad:

  • Uso de registros (en Java 14): En Java, la función de registro proporciona una forma concisa de crear clases de datos inmutables.
public record ImmutablePoint(int x, int y) {}
  • Usar estructuras de datos inmutables: Utilizar estructuras de datos inmutables existentes proporcionadas por el lenguaje de programación o las bibliotecas, como:
  1. Java: Colecciones.listainmodificable(), Lista.de(), Conjunto.de()

  2. C#: ImmutableList, ImmutableArray de System.Collections.Immutable

  3. Python: Las tuplas son inherentemente inmutables.

  • Usar campos finales: Declarar los campos de una clase como finales. Esto garantiza que los campos solo se puedan asignar una vez, durante la construcción del objeto.

  • Sin configuradores: Evite proporcionar métodos de configuración para campos mutables. Esto evita que el código externo cambie el estado de un objeto una vez construido.

public final class ImmutablePoint {
    private final int x;
    private final int y;

    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}
  • Métodos estáticos de fábrica: En lugar de proporcionar un constructor público, utilice métodos estáticos de fábrica que devuelvan nuevas instancias del objeto, dejando claro que el estado no se puede cambiar

  • Patrón de creación (para objetos complejos): Para objetos que requieren muchos parámetros, utilice el patrón de creación para crear objetos inmutables. El constructor acumula los parámetros y construye una instancia inmutable al final.

Beneficios

  • Concurrencia: Si la estructura interna de un objeto inmutable es válida, siempre será válida. No hay posibilidad de que diferentes subprocesos puedan crear un estado no válido dentro de ese objeto. Por lo tanto, los objetos inmutables son Thread Safe.

  • Recolección de basura: Es mucho más fácil para el recolector de basura tomar decisiones lógicas sobre objetos inmutables.

Outro

Dotarte de este conocimiento no solo mejora tu capacidad para escribir código de alto rendimiento, sino que también te prepara para los desafíos del desarrollo de software moderno, donde la capacidad de respuesta y la escalabilidad son primordiales. A medida que continúa su viaje hacia el mundo de los subprocesos múltiples, recuerde que cada concepto que domine contribuirá a su crecimiento como desarrollador y a su capacidad para crear aplicaciones que cumplan y superen las expectativas del usuario.

¡Estén atentos, ya que en el próximo artículo nos centraremos en el hambre, el punto muerto, las condiciones de carrera, la programación del sistema operativo y mucho más, que elevarán sus habilidades de programación e impulsarán su carrera!

Referencias

Muchas gracias a la documentación en línea, a la comunidad y a todos los recursos disponibles que hicieron posible este artículo.

  1. Infografía
  2. Comprensión de los conceptos básicos de subprocesos múltiples
  3. Atomicidad
  4. Qué es inmutable

Descargo de responsabilidad: este artículo está asistido por IA. La estructura del artículo y la lista de ideas se seleccionan e investigan 100% manualmente. Reviso todos los textos generados por IA para garantizar la precisión de la información y agregar algunos contextos

Declaración de liberación Este artículo se reproduce en: https://dev.to/anwaar/multithreading-key-concepts-for-engineers-part-1-4g73?1 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3