"Java Programación Concurrente reales" notas de estudio (2)

Capítulo 3: objetos compartidos

visibilidad

Además synchronize, la sincronización también tiene otro importantes aspectos sutiles: visibilidad de memoria. No sólo queremos ser capaces de evitar un hilo modifica el estado del objeto siendo utilizado por otro hilo, pero quería asegurarse de que cuando un hilo modifica un estado del objeto, otros hilos pueden ver realmente el cambio.

En un entorno de un solo subproceso, si se escribe un valor a una variable en primer lugar, a continuación, lea esta variable en ausencia de intervención por escrito, se puede obtener el mismo valor de retorno. Pero cuando se producen lecturas y escrituras en diferentes temas, la situación no es simplemente el caso.

/*
	读线程启动后,主线程虽然把ready赋值为true,
	但是由于线程之间存在缓存问题,读线程的reday仍然是false,未能及时获取最新的reday值。
	导致程序的运行结果与预期不符。
*/
public class NoVisibility {
  private static boolean ready;
  private static int number;

  private static class ReaderThread extends Thread {
    @Override
    public void run() {
      while (!ready) {
        Thread.yield();
      }
      System.out.println(number);
    }
  }

  public static void main(String[] args) {
    new ReaderThread().start();
    number = 42;
    ready = true;
  }
}

Cerradura y la visibilidad

Al realizar un hilo de bloques de sincronización A, entonces el hilo B también entra en el bloque de sincronización es el mismo monitor de bloqueo, el caso se puede asegurar que el mismo es visible después de que el bloqueo se libera antes de que el valor de una variable es visible, a adquirir el bloqueo B .
Aquí Insertar imagen Descripción

Cerradura no se trata sólo de la sincronización y la exclusión mutua, sino también acerca de la memoria visible. Con el fin de asegurar que todos los temas son capaces de ver el último valor compartido, las variables mutables que implican la lectura y escritura de los hilos de las mismas variables compartidas deben estar sincronizados utilizando una cerradura común.


variables volátiles

lenguaje Java también ofrece otras opciones, a saber, una forma débil de la sincronización: volatilevariable.

Asegura que actualiza una variable de una manera predecible para informar a otros hilos.

Cuando un campo se declara como volatileel tipo, monitores compiladores y variables en tiempo de ejecución: se comparte, y su funcionamiento no será reordenada y de otras operaciones de memoria.

Por lo tanto, leer un volatiletipo de tiempo de las variables siempre devuelve el valor más reciente escrito por un poco de hilo.

Acceso a volatilevariables de funcionamiento no están bloqueados, que no causa la obstrucción hilo de ejecución, lo que hace volatilerelativas variables sychronizedtérminos, pero mecanismo de sincronización de peso ligero.

De bloqueo puede asegurar la visibilidad y la resistencia átomo; volatilevariables pueden asegurar la visibilidad.

Sólo después de que todos los siguientes criterios cumplidos, puede utilizar volatilevariables:

  • No depende del valor actual de las variables al escribir variables, o ser capaz de garantizar que sólo un único hilo de modificar los valores de las variables;
  • Variable no tiene que participar en otras variables de estado de restricción constante;
  • Y cuando se accede a las variables, no hay ninguna otra razón para bloquear.

NOTA: Las variables atómicas java.util.concurrent.atomic()


Tema cerrado

El acceso a una sincronización de datos variable compartida requiere. Para evitar de una manera sincronizada no es de datos común. Si se accede a los datos sólo en un solo hilo, que no necesita ninguna sincronización.

cerró la tecnología de hilo (hilo de confinamiento) es una de las maneras más fáciles de lograr flujos seguros.

Cuando el objeto está encerrado en un hilo, este enfoque será apta para subprocesos de forma automática, incluso si el objeto en sí mismo no está cerrada.

Una aplicación común es la de limitar el uso de hilo el grupo de aplicaciones de JDBC (Java Database Connectivity) objeto de conexión.

La especificación JDBC no requiere objetos de conexión son thread-safe.

Cada hilo se encargará de la mayoría de las solicitudes de forma sincrónica (tales como solicitudes Servlet o EJB (Enterprise Java Bean) llamada), sino también en el objeto de conexión antes de ser devuelto, la piscina no se redistribuye a otros temas, por lo que esta gestión de la conexión objeto de conexión de modo implícitamente limitado en el hilo durante el procesamiento de la solicitud.

El límite de la pila

El límite de la pila (también llamado roscas internas o el uso de hilo local, pero no el núcleo clases de biblioteca ThreadLocalconfusión) es un caso especial de los límites de rosca, los límites en la pila, se puede alcanzar el objetivo únicamente por variables locales.

A medida que el paquete hace que sea más fácil ser constante restricción retenida, la variable local se limita a hacer que el objeto más fácilmente en el hilo local.

La variable local en sí está limitada a un hilo de ejecución, que están presentes en la pila de hilo de ejecución. Otros hilos no pueden acceder a la pila.

ThreadLocal

de forma más estandarizada de mantener un límite de la rosca es usar Threadlocal, que le permite asociar un objeto con cada hilo al valor de retención. ThreadLocalProporciona getel setdispositivo de acceso, uso para mantener un hilo separado para cada copia. Así que getsiempre devuelto por el hilo de ejecución actual por setel último valor establecido.


inmutabilidad

Después de la creación de un estado que no puede ser modificado objeto se llama objetos inmutables.

Los objetos inmutables siempre será seguro para subprocesos.

Tanto el modelo de memoria de Java Language Specification y Java no están en la definición formal de la inmutabilidad, pero inmutabilidad no es simplemente igual a se declaran como todos los objetos de dominio finaltipo, todos los campos son finaltipos de objetos aún pueden ser variables debido a que el finalcampo de referencia para obtener un objeto variable.

Sólo satisface la siguiente condición, un objeto es inmutable:

  • Su condición no se puede modificar después de la creación;
  • Todos los campos son finaltipos; y,
  • Fue creado correctamente (creación no ocurrió esta fuga de referencia durante).

StringEs un ejemplo típico de los objetos inmutables en Java.


Capítulo 4: Agrupación de objetos

-Seguro para hilos clase de diseño

clase thread-safe Diseño de proceso debe incluir los siguientes tres elementos básicos:

  • La determinación del estado del objeto que se compone de una variable;
  • Invariantes determinan los límites de variables de estado;
  • Desarrollar una estrategia de gestión de acceso simultáneo al estado del objeto.

Glosario:

  • condición Priori (condición previa): Método para (método), que define el método antes de llamar a las condiciones que deben ser verdaderas. Por ejemplo, no se puede quitar una entrada de una cola vacía: Antes de eliminar un elemento, la cola debe estar en estado "no vacío".
  • Después de las condiciones experimentales (postcondition): se refiere a métodos, que define las condiciones reales del proceso después de la aplicación con éxito debe ser completado. Por ejemplo, si el estado actual del contador 1 Valor mínimo de 17, el siguiente estado sólo es legítimo 18.

Ejemplos de restricciones

Incluso si un objeto no es seguro para subprocesos, todavía hay muchas tecnologías pueden hacer que sea seguro para los programas multihilo.

Por ejemplo, usted puede estar seguro de que es el acceso de un único subproceso (límite de la rosca), también puede asegurarse de que todo el acceso está protegido por las cerraduras correctamente.

Los datos se encapsula en el interior del objeto, el acceso limitado al objeto de datos en el método, el hilo siempre es más fácil asegurar que los datos de acceso de bloqueo correcto.

/**
 * 使用限制确保线程安全
 */
@ThreadSafe
public class PersonSet {
    @GuardedBy("this")
    private final Set<Person> mySet = new HashSet<Person>();

    public synchronized void addPerson(Person p) {
        mySet.add(p);
    }
    public synchronized boolean containsPerson(Person p) {
        return mySet.contains(p);
    }
}

Hay muchos ejemplos hilos de plataforma limitado de la biblioteca, incluyendo algunos de clase, su existencia es llevar clases no compatibles con el proceso en un hilo de seguridad.

ArrayListY HashMaptales recipientes básicas no a modo de hilo de seguridad, pero biblioteca de clases de envoltura proporciona un método de la planta ( Collections.synchronizedListy el método de la misma familia), de tal manera que las clases no de hilos de seguridad pueden ser utilizados con seguridad en un entorno multiproceso.


Agregar funcionalidad a las clases seguras para subprocesos existentes

" La falta que se añade a (put-si-ausente)" El concepto es bastante sencillo once primer cheque antes de añadir un elemento al contenedor si ya existe, si existe, no añada.

( " Registro de gestión (registro de entrada, entonces-acto)" Ahora que sonó la alarma).

requisitos de seguridad para la clase de hilo implícitamente añadieron otros once condiciones como "Falta saber, añadiendo que" este tipo de operaciones deben ser atómicas.

Hay cualquier solicitud razonable le dirá, si tiene un objeto de lista que no contiene X, y realizaron dos veces "añadiendo que no se encuentra," el ADDX, entonces el resultado del envase sólo debe contener una copia de la X.

Sin embargo, si "Missing es decir añadió" operaciones atómicas no son, en cierto momento esporádica, los dos hilos no están en el contenedor para ver X, y realizar la ADDX, causa el recipiente contiene dos copias de X.

  • Añadir una nueva operación atómica más segura es modificar la clase original para apoyar la operación deseada.
    Pero no podrá acceder o no hay libertad para modificar el código fuente, por lo que suele ser imposible.
    Incluso si se puede modificar la clase original, estrategia de sincronización también es necesario para entender su aplicación, con el fin de mejorar su función bajo la premisa de mantener el diseño original.
    Se añade el nuevo método directamente a la clase, significa que toda la directiva de sincronización clase de implementación de código todavía contiene el código fuente en un archivo, tan fácil de entender y mantener.

  • Otra forma es extender la clase si la clase está diseñada para extenderse.
    Añadir 4,13 BetterVectorextiende Vectory añade un putIfAbsentmétodo. A pesar de la expansión de Vectorla práctica es bastante intuitivo, pero no todas las clases dio expone las subclases de un número suficiente de estados para apoyar este programa.

@ThreadSafe
public class BetterVector<E> extends Vector<E> {
  public synchronized boolean putIfAbsent(E x) {
    boolean absent = !contains(x);
    if (absent) {
      add(x);
    }
    return absent;
  }
}
Publicados 107 artículos originales · ganado elogios 88 · vistas 260 000 +

Supongo que te gusta

Origin blog.csdn.net/Code_shadow/article/details/104357789
Recomendado
Clasificación