Stream synchronization for multiple readers / single writers in Clojure

I have unsafe code (a writer for shared data) that can only be called from multiple threads in a serialized way, but I don’t want to block any other thread-safe work (multiple readers) when this code is not called.

This, in fact, is a situation of blocking of the type of multiple reading / single writer, where writers should exclude both readers and other authors.

i.e. I have two functions:

(defn reader-function [] ....) // only reads from shared data

(defn writer-function [] ....) // writes to shared data

And the number of threads that are executed (possibly in a loop) are as follows:

(do 
  (reader-function)
  ...
  (writer-function))

If any one thread has a write function, all other threads should be blocked. that is, at any moment in time:

  • one thread is executed by the writer and all others are blocked
  • , , , .

Clojure?

+3
2

ref. Clojure ( Java). dosync, .

. , - alter. (dosync). , dosync, dosync , , - , .

(defn reader [shared] 
  (println "I see" @shared))

(defn writer [shared item]
  (dosync 
    (println "Writing to shared")
    (alter shared conj item)))

;; combine the read and the write in a transaction
(defn combine [shared item]
  (dosync 
    (reader shared)
    (writer shared item)))

;; run a loop that adds n thread-specific items to the ref
(defn test-loop [shared n]
  (doseq [i (range n)]
    (combine shared (str (System/identityHashCode (Thread/currentThread)) "-" i))
    (Thread/sleep 50)))

;; run t threads adding n items in parallel
(defn test-threaded [t n]
  (let [shared (ref [])]
    (doseq [_ (range t)]
      (future (test-loop shared n)))))

- (test-threaded 3 10).

: http://clojure.org/refs

, , , . .

+3

java.util.concurrent.locks.ReentrantReadWriteLock. , .

0

Source: https://habr.com/ru/post/1787141/


All Articles