20. Contenedores concurrentes: ¿Qué fosas necesitamos llenar? -Herramientas de concurrencia

1. Contenedor de sincronización y sus precauciones

En 12. ¿Cómo escribir programas concurrentes con pensamiento orientado a objetos? Introducir el pensamiento orientado a objetos para escribir programas concurrentes.


class SafeArrayList<T> {
//	封装	ArrayList
	List<T> c = new ArrayList<>();

//	控制访问路径
	synchronized T get(int idx) {
		return c.get(idx);
	}

	synchronized void add(int idx, T t) {
		c.add(idx, t);
	}

	synchronized boolean addIfNotExist(T t) {
		if (!c.contains(t)) {
			c.add(t);
			return true;
		}
		return false;
	}
}

Esto es muy simple para lograr la seguridad del hilo.
Hay clases seguras para subprocesos en Java SDk, que envuelven respectivamente ArrayList,
HashSet y HashMap en List, Set y Map para subprocesos.

List list = Collections.synchronizedList(new ArrayList());
Set set = Collections.synchronizedSet(new HashSet());
Map map = Collections.synchronizedMap(new HashMap());

La combinación de operaciones requiere atención a las condiciones de carrera, incluso si cada operación puede garantizar la atomicidad, no puede garantizar la atomicidad de las operaciones combinadas.

Un "pozo" que se pasa por alto fácilmente en el campo del contenedor es atravesar el contenedor con un iterador . El siguiente método no garantiza la atomicidad de la operación de combinación.

List list = Collections.synchronizedList(new ArrayList());
Iterator i = list.iterator();
while (i.hasNext())
foo(i.next());

El enfoque correcto es el siguiente:

List list =	Collections.synchronizedList(new ArrayList());
synchronized (list)	{		
Iterator	i	=	list.iterator();	
while	(i.hasNext())
foo(i.next());
}				

El método público de la clase contenedora bloquea esto del objeto, que es la lista aquí.

2. Contenedores concurrentes y sus precauciones.

Todos los métodos de contenedores síncronos están sincronizados y bloqueados, y el rendimiento es pobre. Después de java1.5, se proporciona un contenedor con mejor rendimiento. Generalmente lo llamamos contenedor concurrente.

Los contenedores concurrentes comúnmente utilizados son los siguientes:
Inserte la descripción de la imagen aquí

2.1 Lista

CopyOnWriteArrayList, CopyOnWrite hará una nueva copia de la variable compartida al escribir. La ventaja de esto es que la operación de lectura está completamente libre de bloqueos.

CopyOnWriteArrayList mantiene una matriz internamente, y la matriz variable miembro apunta a esta matriz interna. Todas las operaciones de lectura se basan en la matriz, como se muestra en la siguiente figura, iterador iterador atraviesa la matriz de matriz.
Inserte la descripción de la imagen aquí
Si hay una operación de escritura al recorrer la matriz, como agregar elementos, ¿cómo se maneja CopyOnWriteArrayList? CopyOnWriteArrayList copiará una matriz, y luego realizará la operación de agregar elementos en la matriz recién copiada, y luego apuntará la matriz a esta nueva matriz después de la ejecución. Como puede ver en la figura siguiente, la lectura y la escritura se pueden realizar en paralelo: la operación transversal siempre se realiza en función de la matriz original, mientras que la operación de escritura se realiza en función de la nueva matriz.
Inserte la descripción de la imagen aquí
Tenga en cuenta el pozo:

  • Escenarios de aplicación, CopyOnWriteArrayList solo es adecuado para escenarios con muy pocas operaciones de escritura, y puede tolerar inconsistencias a corto plazo en lectura y escritura.
  • El iterador CopyOnWriteArrayList es de solo lectura y no admite la adición, eliminación o modificación.

2.2 Mapa

Las dos implementaciones son ConcurrentHashMap y ConcurrentSkipListMap, la principal diferencia es que la clave de ConcurrentHashMap no está ordenada y la clave de ConcurrentSkipListMap está ordenada . No se permite que la clave y el valor de ambos sean nulos; de lo contrario, se informará un error.
Inserte la descripción de la imagen aquí
ConcurrentSkipListMap usa skip table, que tiene un mejor rendimiento.

2.3 Set

Las dos implementaciones de la interfaz Set son CopyOnWriteArraySet y ConcurrentSkipListSet. Para escenarios de uso, puede consultar CopyOnWriteArrayList y ConcurrentSkipListMap descritos anteriormente, y sus principios son los mismos.

2.4 Cola

Clasificación a partir de dos dimensiones.

  • Bloqueo y no bloqueo , el llamado bloqueo se refiere a cuando la cola está llena, la operación de la cola está bloqueada, cuando la cola está vacía, la operación de la cola está bloqueada;
  • De un solo extremo y de dos extremos, de un solo extremo se refiere al equipo que solo puede ingresar al equipo al final del equipo, el primer equipo fuera; y el de doble extremo se refiere al equipo que al final del equipo puede entrar y salir del equipo.

Las colas de bloqueo se identifican mediante la palabra clave Blocking, las colas de un solo extremo se identifican por Queue y las colas de doble final se identifican por Deque .

  1. Cola de bloqueo de un solo extremo: de hecho, ArrayBlockingQueue, LinkedBlockingQueue, SynchronousQueue, LinkedTransferQueue, PriorityBlockingQueue y DelayQueue. Internamente, habrá una cola. Esta cola puede ser una matriz (cuya implementación es ArrayBlockingQueue) o una lista vinculada (cuya implementación es LinkedBlockingQueue); incluso no puede contener la cola (cuya implementación es SynchronousQueue). La operación en cola debe esperar la operación en cola del hilo del consumidor. LinkedTransferQueue combina las funciones de LinkedBlockingQueue y SynchronousQueue, y su rendimiento es mejor que LinkedBlockingQueue; PriorityBlockingQueue admite la eliminación de cola de acuerdo con la prioridad; DelayQueue admite la retirada de cola retrasada.
    Inserte la descripción de la imagen aquí
    2. Cola de bloqueo de doble extremo: su implementación es LinkedBlockingDeque.
    Inserte la descripción de la imagen aquí
    Solo ArrayBlockingQueue y LinkedBlockingQueue son compatibles. Cuando se usan otras colas no limitadas, debemos considerar completamente si existen peligros ocultos que causen OOM.
97 artículos originales publicados · elogiados 3 · 10,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/qq_39530821/article/details/102655814
Recomendado
Clasificación