A Java actor library for parallel execution? Isn’t it Clojure?!

While reading the article A Java actor library for parallel execution, I’ve been wondering if and how it could be achieved in Clojure. Since Clojure provides concurrency abstractions: vars, atoms, agents and refs, it should be easily doable.

From the section “Actor concurrency on the Java platform”:

“Actor-based systems make parallel processing easier to code by implementing a message-passing scheme. In this scheme, each actor in the system can receive messages; perform actions requested by the messages; and send messages to other actors, including themselves, to perform complex sequences of operations. All messages between actors are asynchronous, meaning that the sender continues processing before any reply is received. An actor’s life may be thus spent in an indefinite loop of receiving and processing messages.”

It exactly resembles what I could learn about Clojure’s agents (quoting from their web page):

  • “Agents provide shared access to mutable state.”
  • “Agents provide independent, asynchronous change of individual locations.”
  • “Agents are bound to a single storage location for their lifetime, and only allow mutation of that location (to a new state) to occur as a result of an action. Actions are functions (with, optionally, additional arguments) that are asynchronously applied to an Agent’s state and whose return value becomes the Agent’s new state.”

When you apply the knowledge to how actor-based systems were presented in the article, one may have drawn a conclusion they’re alike. I’m not good at the topic, but the main difference between Clojure’s agents and actor-based systems is their scope – a single JVM vs a distributed system of a bunch of JVMs. The former is Clojure’s agents while the latter represent what Scala’s Akka provides and these μJavaActors. There’s another difference I’m aware of – Clojure’s agents provide a lock-free, almost instantaneous read whilst actor-based systems require another (read) message to be queued and ultimately processed. At a higher-level of abstraction, they’re alike, but the scope – a JVM vs JVMs – a good sense of their pros and cons is highly appreciated.

A message for an agent is a function that’s “asynchronously applied to an Agent’s state and whose return value becomes the Agent’s new state.” (quoting Clojure agent’s documentation). It’s simple like that. You call a function with three or more arguments (the agent, a function and its other input arguments beside the current state of the agent) and at some point (asynchronous operation) the function sent is applied. Clojure STM will take care of any problems with the function’s execution so re-calls are expected in a highly-concurrent write access.

Unlike actors, Clojure’s agents doesn’t require that you create “a container for three (optional) values and some behavior” (from Introducing μJavaActors). It’s a function, possibly a pure one and what it returns becomes the new state of the agent.

I think the article’s ActorManager is Clojure itself for agents whilst the Actor is a agent.

I’m working on a code that would even partially show the features presented in the article. I wish I could do that now, but when I began the development I realized it would take me a while. I need spend some time with Java Swing to develop a nice GUI for the demo.

I’ve however built a smaller application to process messages that decrement a number held by 5 agents.

(ns agents)

(def agents (map agent (range 0 5)))

(defn pick-agent [as]
  (let [idx (rand-int (count as))]
    (nth as idx)))

(defn dec-msg [s as]
  (let [_ (println "Agent: " *agent*)]
    (cond
      (pos? s) (let [_ (println ">>> pos?")
                     a (pick-agent as)]
                 (send a dec-msg as)
                 (dec s))
      :default (let [_ (println ">>> :default")
                     fas (remove (partial = *agent*) as)
                     a (pick-agent fas)]
                 (send a dec-msg fas)
                 s))))
 
(send (pick-agent agents) dec-msg agents)

How does it look? Comments appreciated.

Be Sociable, Share!
This entry was posted in Languages.

Leave a Reply

%d bloggers like this: