在clojure中锁定惯用文件?

时间:2011-06-19 19:42:36

标签: clojure

我从一个涉及写入文件的队列中有一组期货处理作业。确保只有一个未来一次访问特定文件的惯用方法是什么?

3 个答案:

答案 0 :(得分:8)

如何使用代理而不是锁来确保这一点?

我认为使用代理来保护共享的可变状态,无论它是在内存中还是在磁盘上,在clojure中比使用锁更具惯用性。

如果您一次创建一个代理并将访问尝试发送给代理,则可以确保仅在线程上访问给定文件。

例如:

(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)))

然后通过代理附加您的文件:

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

如果您需要同步使用该文件,可以通过等待来实现。像这样:

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

答案 1 :(得分:4)

我会使用核心Clojure函数locking,其使用方法如下:

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

此处some-object可以是文件本身,也可以是您想要同步的任意对象(如果您想要一个锁来保护多个文件,这可能是有意义的。)

在幕后,它使用标准的JVM对象锁定,因此它基本上等同于Java中的同步代码块。

答案 2 :(得分:1)

我认为在Clojure中没有特定的内置函数,但您可以使用标准的Java IO函数来执行此操作。这看起来像这样:

(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)