2014-05-19 77 views
1

经过短期研究,我在两个进程之间发生并发问题我已经看到temporary file被建议解决此问题。使用File#flock作为ruby全局锁(进程互斥量)

所以解决办法是创建/tmp/global.lock并将其用作全局锁。我在此线程中找到的示例Mutex for Rails Processes

迄今为止对我有意义,但我希望看到此解决方案的最佳实践。以上解释是有道理的,但我不知道如何检查给定文件是否被锁定?

fh = File.open("/some/file/path", File::CREAT) 

begin 
    if locked = check_file_locked?() 
    sleep(1) 
    else 
    fh.flock(File::LOCK_EX) 
    # do what you need to do 
    end 
ensure 
    fh.flock(File::LOCK_UN) 
end 

这是我的解决方案的理解和不知道如何实现提及check_file_locked?()?另外如果有最好的方法会喜欢听到它。

回答

4

当你对文件进行独占锁定时,试图在ruby中再次锁定它将无限期地等待,直到文件解锁,所以你可以依靠它并设置一个超时时间ruby应该等待多久,这可能不是最恰当的方式,但我会如下操作:

fh = File.open("/some/file/path", File::CREAT) 
fh.flock(File::LOCK_EX) 

require 'timeout' 
def check_file_locked?(file) 
    f = File.open(file, File::CREAT) 
    Timeout::timeout(0.001) { f.flock(File::LOCK_EX) } 
    f.flock(File::LOCK_UN) 
    false 
rescue 
    true 
ensure 
    f.close 
end 
f = File.open("/tmp/a.txt", "w+") 
f.flock(File::LOCK_EX) 
check_file_locked?("/tmp/a.txt") # => true 
f.flock(File::LOCK_UN) 
check_file_locked?("/tmp/a.txt") # => false 
+0

谢谢你,优秀的写了。 –

0

@ bjhaid的答案可能会导致超时超时#Rubinius中引起翻译错误的问题。这也是不必要的复杂。

这里有一个简单的版本,使用nonblocking锁,而不是超时:

def locked? lockfile_name 
    f = File.open(lockfile_name, File::CREAT) 

    # returns false if already locked, 0 if not 
    ret = f.flock(File::LOCK_EX|File::LOCK_NB) 

    # unlocks if possible, for cleanup; this is a noop if lock not acquired 
    f.flock(File::LOCK_UN) 

    f.close 
    !ret # ret == false means we *couldn't* get a lock, i.e. it was locked 
end