2011-09-18 12 views
9

Si quiero mantener un contador global (por ejemplo, para contar el número de solicitudes entrantes a través de varios hilos), entonces la mejor manera de hacerlo en Java sería usar un int volátil. Suponiendo que se use clojure, ¿hay una forma mejor (mejor rendimiento) de hacer?contador sincronizado en clojure

Respuesta

13

Me gustaría hacer esto con una atom en Clojure:

(def counter (atom 0N)) 

;; increment the counter 
(swap! counter inc) 

;; read the counter 
@counter 
=> 1 

Esto es totalmente seguro para subprocesos, y sorprendentemente alto rendimiento. También, ya que utiliza la manipulación numérica abitrary precisión de Clojure, no es vulnerable a desbordamientos de enteros en la forma en que un int volátil puede ser .....

+0

habría que proporcionar un mejor rendimiento y luego usando un int volátil? en caso afirmativo, cualquier idea sobre por qué/cómo es mejor. – 142857

+1

Un átomo sería un poco más lento que un int volátil. Pero a menos que esté contando millones de eventos por segundo, la diferencia no sería lo suficientemente grande como para darse cuenta. Y a ese nivel de rendimiento, una int volátil se desbordará en menos de una hora de todos modos ...... – mikera

+3

En Clojure 1.3, puede desbordarse: '(swap! (Átomo 9223372036854775807) inc)' arroja una excepción de desbordamiento. La solución es usar BigInts: '(swap! (Átomo 9223372036854775807N) inc)' o la función 'inc'' de promoción automática –

7

definir un contador global como agent

(def counter (agent 0)) 

para aumentar el valor contenido en el agente que send una función (en este caso inc) al agente:

(send counter inc) 

para leer el valor actual puede utilizar deref o laMacro del lector:

@counter ;; same as (deref counter) 

Los agentes son solo uno de varios tipos de referencia disponibles. Puede leer más acerca de estas cosas en el sitio web de Clojure:

Cuestiones relacionadas