首页 > 解决方案 > Ruby 多进程同步

问题描述

我有一段处理多个文件的 ruby​​ 代码。它的工作原理大致是这样的,

1)check the 'done' json file to ignore files which have already been processed.
2)Pick up a file from remaining files to process
3)process the file
4)write a entry in 'done' file
5)repeat

我试图让它在多进程环境中运行,目标是在不同的 shell 中多次运行 ruby​​ 文件。

我遇到的第一个问题是在第 1 部分。当多个进程试图获取下一个要处理的文件时存在竞争条件。也就是当条目不在“完成”文件中时,多个进程可以获取同一个文件处理。(为此我引入了一个 .lock 文件)

此外,一个进程需要知道另一个进程当前正在处理哪个文件,因此也可以忽略它。(为此,我引入了一个“并发文件”)

现在我的算法看起来像这样,

1)wait for the .lock file to be not there
2)create the .lock file
3)read and ignore the files listed in the 'done' file
4)read and ignore the files listed in the 'concurrent' file
5)choose a file to process
6)write a entry in the 'concurrent' file
7)delete the .lock file
8)process the file
9)remove the entry from 'concurrent' file
10)add a entry in 'done' file
11)repeat

现在它似乎工作了,直到我开始创建超过 5 个进程。

经过一番调试,我发现多个进程正在同时创建 .lock 文件。

这是我的同步代码,

def wait_for_key
  loop do
    if File.exists? "#{file_path}/.lock"
      puts "waiting for lock to be released"
      sleep 1
    else
      break
    end
  end
end

def lock
  FileUtils.touch "#{file_path}/.lock"
  puts "download method locked #{Time.now}"
end

def release_lock
  FileUtils.rm "#{file_path}/.lock"
  puts "lock released #{Time.now}"
  sleep 1
end

所以并发算法大致是这样运行的,

wait_for_key
lock
.....do some stuff 
release_lock

因此,如果多个进程同时触发 lock 方法,则 wait_for_key 方法中似乎存在竞争条件。即多个进程看到 .lock 文件不存在,而不是同时调用 lock 方法。

我真的不知道从哪里开始,我研究了 ruby​​ mutex 但它看起来只适用于多个线程。

任何想法将不胜感激!

标签: rubyprocesssynchronization

解决方案


  1. 您可以在生成子进程之前确定需要处理哪些文件。

  2. 如果您可以访问 Redis 服务器,则将这些文件名放入 Redis 列表中,然后生成子进程并让它们一次弹出一个文件名并进行处理,直到列表为空。如果您无权访问 Redis,则可以将文件平均分配给子进程。在这两种情况下,您都不需要全局锁或互斥锁。


推荐阅读