Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Clojure concurrency example

I just go through various documentation on Clojure concurrency and came accross the example on the website (http://clojure.org/concurrent_programming).

(import '(java.util.concurrent Executors))
(defn test-stm [nitems nthreads niters]
(let [refs  (map ref (replicate nitems 0))
      pool  (Executors/newFixedThreadPool nthreads)
      tasks (map (fn [t]
                   (fn []
                     (dotimes [n niters]
                       (dosync
                         (doseq [r refs]
                           (alter r + 1 t))))))
                (range nthreads))]
(doseq [future (.invokeAll pool tasks)]
  (.get future))
(.shutdown pool)
(map deref refs)))

I understand what it does and how it works, but I don't get why the second anonymous function fn[] is needed?

Many thanks,

dusha.

P.S. Without this second fn [] I get NullPointerException.

like image 647
dusha Avatar asked Jan 06 '11 02:01

dusha


People also ask

What is concurrency in Clojure?

Concurrency refers to a program's ability to carry out more than one task, and in Clojure you achieve this by placing tasks on separate threads. Programs execute in parallel when a computer has more than one CPU, which allows more than one thread to be executed at the same time.

Is Clojure multithreaded?

Clojure simplifies multi-threaded programming in several ways. Because the core data structures are immutable, they can be shared readily between threads. However, it is often necessary to have state change in a program.

What is concurrency in parallel computing?

Concurrency is when multiple tasks can run in overlapping periods. It's an illusion of multiple tasks running in parallel because of a very fast switching by the CPU. Two tasks can't run at the same time in a single-core CPU. Parallelism is when tasks actually run in parallel in multiple CPUs.

What is concurrency in programming?

Concurrency means multiple computations are happening at the same time. Concurrency is everywhere in modern programming, whether we like it or not: Multiple computers in a network. Multiple applications running on one computer. Multiple processors in a computer (today, often multiple processor cores on a single chip)


1 Answers

Here is a classic example of using higher-order functions:

;; a function returns another function
(defn make-multiplyer [times]
  (fn [x]
    (* x times)))

;; now we bind returned function to a symbol to use it later
(def multiply-by-two (make-multiplyer 2))

;; let's use it
(multiply-by-two 100)   ; => 200

In that code sample fn inside fn works the same way. When map invokes (fn [t] (fn [] ...)) it gets inner fn.

(def list-of-funcs (map (fn [t]
                          (fn [] (* t 10)))   ; main part
                        (range 5)))
;; Nearly same as
;; (def list-of-funcs (list (fn [] (* 0 10))
;;                          (fn [] (* 1 10))
;;                          ...
;;                          (fn [] (* 4 10))))


(for [i list-of-funcs]
  (i))
; => (0 10 20 30 40)

Update: And as Alex said tasks in the code sample is bound to list of callables which is passed then to .invokeAll().

like image 65
koddo Avatar answered Oct 17 '22 22:10

koddo