2009-09-01 21 views

Respuesta

8

No puedo hablar sobre Clojure específicamente, pero ... significa que no necesita esperar a que alguien termine con algo antes de poder ir a trabajar. Lo cual es genial.

Normalmente se consigue con tipos inmutables. Si no se puede modificar nada, no es necesario que espere hasta que alguien haya terminado antes de poder acceder.

+2

¿Quién es 'alguien'? ¿Podría dar un ejemplo? No creo que haya "alguien compartiendo mis objetos conmigo". Tal vez debería revisar debajo de la cama. –

+4

* alguien * es solo otra pieza de código, en otro hilo, que accede a ese objeto. –

+0

A veces es más rápido, algunas veces más lento, como la mayoría de las optimizaciones que se realizan sin medir. Así que a veces es algo bueno, y a veces esos bloqueos hubieran sido mejores. Es por eso que nos llamamos ** ingenieros de software **. – Eloff

5

Bloqueos. O para ser más correctos la falta de ellos.

Uno de los mayores problemas en la mayoría de los idiomas es que usted termina con los puntos muertos que son:

  1. infierno en la tierra de depurar.
  2. Difícil para asegurarse de que se ha librado.

Ahora, sin bloqueos, obviamente no se encontrará con interbloqueos.

+0

Nunca me encontré con un punto muerto que conocía. ¿Está sucediendo con más frecuencia de lo que creo? Supongo que no estoy familiarizado con este problema aunque he programado mucho. Los únicos problemas de bloqueo que he tenido conocimiento estaban en la base de datos. –

+0

@i_like_monkeys Si está escribiendo un webfrontend en C#, la mayoría de los problemas de bloqueo van a estar en las capas inferiores (el servidor web y la base de datos), pero si va a desarrollar programas definitivamente es un problema. – tomjen

+0

Si tiene un punto muerto, el síntoma generalmente será que su programa se congele (0% de uso de CPU, ninguna de sus tareas se realiza, nunca más, hasta que lo mate manualmente con el Administrador de tareas, etc.). Los bloqueos pueden ocurrir si sus subprocesos tienen más de un bloqueo a la vez, y diferentes subprocesos están adquiriendo los bloqueos en un orden diferente. –

1

El beneficio de la simultaneidad sin cerraduras es la falta de complejidad en el programa. En lenguajes imperativos, la programación concurrente depende de bloqueos, y una vez que el programa llega a ser moderadamente complejo, los errores de interbloqueo difíciles de arreglar se infiltran.

+0

¿Te ha pasado esto alguna vez? –

9

La concurrencia sin bloqueo también proporciona la agradable ventaja de que los lectores nunca tienen que esperar a otros lectores . Esto es especialmente útil cuando muchos hilos leerán datos de una sola fuente. Aún necesita definir las dependencias de datos en su programa y definir explícitamente las partes de una transacción que se pueden conmutar de manera segura.
STM le salva de interbloqueos y casi todas las instancias de livelock aunque no le ahorra errores de concurrencia aún puede crear casos donde una transacción fallará porque carece de los recursos para mantener su historial, pero la parte importante es que fallas de concurrencia será explícito y podrá recuperarlos

+0

¡Sip! STM = memoria transaccional del software. Es un buen trabajo para buscar si quieres saber más sobre cómo funciona esto. –

+2

en Clojure STM, los lectores ni siquiera tienen que esperar a que otros escritores (a menos que quieran hacer una lectura transaccional para obtener una instantánea coherente en múltiples referencias) – mikera

+0

'los lectores nunca tienen que esperar a otros lectores' En el mundo imperativo, los bloqueos de lectura y escritura proporcionan esta funcionalidad :) – vemv

2

Siempre que escriba programas estrictamente secuenciales (haga A, luego B, luego C; terminado!) no tendrá problemas de concurrencia, y los mecanismos de concurrencia de un idioma permanecerán irrelevantes .

Cuando se gradúa de programas de "ejercicio de programación" a cosas del mundo real, muy pronto se encontrará con problemas cuya solución es multi-threading (o el sabor de concurrencia que tenga disponible).

Caso: Programas con una GUI. Digamos que estás escribiendo un editor con revisión ortográfica. Desea que el corrector ortográfico lo haga silenciosamente en segundo plano, pero desea que la GUI acepte sin problemas las entradas del usuario. Entonces ejecuta esas dos actividades como hilos separados.

Caso: Recientemente escribí un programa (para el trabajo) que reúne estadísticas de dos archivos de registro y los escribe en una base de datos. Cada archivo tarda aproximadamente 3 minutos en procesarse. Moví esos procesos en dos hilos que corren uno al lado del otro, reduciendo el tiempo de procesamiento total de 6 minutos a un poco más de 3.

Caso: software de simulación científica/ingeniería. Hay muchos y muchos problemas que se resuelven al calcular algún efecto (flujo de calor, por ejemplo) en cada punto de una cuadrícula tridimensional que representa el sujeto de prueba (núcleo estelar, explosión nuclear, dispersión geográfica de una población de insectos ...). Básicamente, el mismo cálculo se realiza en cada punto y en muchos puntos, por lo que tiene sentido hacerlos en paralelo.

En todos esos casos y muchos más, cada vez que dos procesos informáticos acceden a la misma memoria (= variables, si lo desea) más o menos al mismo tiempo, existe la posibilidad de que interfieran entre sí y estropeen el trabajo de los demás. La gran rama de Computer Science que se ocupa de la "programación simultánea" trata con ideas sobre cómo resolver este tipo de problema.

Se puede encontrar una discusión inicial bastante útil de este tema in Wikipedia.

0

Tal "concurrencia sin cerradura" no es realmente una característica de un idioma; más bien, es una característica de una plataforma o entorno de tiempo de ejecución, y ¡ay! es el lenguaje que no se quitará del camino para darle acceso a estas instalaciones.

Pensar en los intercambios entre simultaneidad basada en bloqueo y sin bloqueo es análogo al problema del evaluador metacircular: se pueden implementar bloqueos en términos de operaciones atómicas (por ejemplo, comparar y cambiar o CAS) y se puede implementar operaciones atómicas en términos de bloqueos. ¿Cuál debería estar en la parte inferior?

5

El mayor problema es que bloqueos no componen.

Si bien es trivial escribir código con una estrategia de bloqueo simple (por ejemplo, ponerlo en una clase Java sincronizada .....), se vuelve más complicado a medida que comienza a bloquear varios objetos y comienza a crear transacciones complejas que combinan diferentes operaciones bloqueadas. Pueden producirse bloqueos, el rendimiento sufre, la lógica de bloqueo comienza a hacer que el código sea extremadamente intrincado y en algún punto el código comienza a quedar inmanejable.

Estos problemas se harán evidentes para cualquiera que tenga que construir un sistema concurrente grande y complejo (y resolverlos fue una gran motivación para Rich Hickey al crear Clojure).

El segundo problema es rendimiento.

Tanto el bloqueo como el STM claramente imponen una sobrecarga. Pero en algunos casos importantes, la sobrecarga de STM puede ser mucho menor.

En particular, la concurrencia sin bloqueos (como con Clojure STM) generalmente implica que los lectores no son perjudicados por ningún otro subproceso (incluidos los escritores) si acceden a los datos fuera de una transacción. Esto puede ser una gran victoria en el caso bastante común que dice que no necesita ser transaccional y supera notablemente las escrituras (creo que la mayoría de las aplicaciones web ...). Las lecturas no transaccionales de una referencia de STM en Clojure son esencialmente libres de sobrecarga.

+0

'Las lecturas no transaccionales de una referencia de STM en Clojure están esencialmente libres de sobrecargas. En principio, ¿deberían leerse las transacciones? Doc dice: "Los lectores y los viajeros nunca bloquearán a escritores, viajeros u otros lectores". – vemv

Cuestiones relacionadas