Idiomatic file lock in clojure?

I have a group of futures that process jobs from a queue that are associated with writing to files. What is the idiomatic way to ensure that only one future will access a specific file at a time?

+7
source share
3 answers

How about using agents instead of locks to ensure this?

I think that using agents to safely save the general changed state, regardless of whether it is in memory or on disk, is more idiomatic in clojure than using locks.

If you create one agent at a time and send attempts to access the agents, you can make sure that only by stream during access to this file.

For example, for example:

(use 'clojure.contrib.duck-streams) (defn file-agent [file-name] (add-watch (agent nil) :file-writer (fn [key agent old new] (append-spit file-name new)))) (defn async-append [file-agent content] (send file-agent (constantly content))) 

then add the file through the agent:

 (async-append "content written to file" (file-agent "temp-file-name")) 

If you require synchronous use of the file, this can be achieved with anticipation. Like this:

 (defn sync-append [file-agent content] (await (send file-agent (constantly content)))) 
+8
source

I would use the Clojure locking kernel function, which is used as follows:

 (locking some-object (do-whatever-you-like)) 

Here, some-object can be either the file itself or an alternative to any arbitrary object that you want to synchronize (which may make sense if you want one lock to protect several files).

Under the hood, a standard JVM object lock is used, which is why it is basically equivalent to a synchronized block of code in Java.

+4
source

I donโ€™t think there is a specific built-in function for this function in Clojure, but you can use the standard java I / O functions for this. It will look something like this:

 (import '(java.io File RandomAccessFile)) (def f (File. "/tmp/lock.file")) (def channel (.getChannel (RandomAccessFile. f "rw"))) (def lock (.lock channel)) (.release lock) (.close channel) 
+1
source

All Articles