在多个进程之间使用锁文件作为锁的正确方法

NoS*_*tAl 5 c++ filesystems race-condition

我有一种情况,其中2个不同的进程(我的C++,其他由JAVA中的其他人完成)是来自某些共享数据文件的编写者和读者.所以我试图通过编写这样的类来避免竞争条件(编辑:这个代码坏了,它只是一个例子)

class ReadStatus
{
    bool canRead;
public:
    ReadStatus()
    {
        if (filesystem::exists(noReadFileName))
        {
            canRead = false;
            return;
        }
        ofstream noWriteFile;
        noWriteFile.open (noWriteFileName.c_str());
        if ( ! noWriteFile.is_open())
        {
            canRead = false;
            return;
        }
        boost::this_thread::sleep(boost::posix_time::seconds(1));
        if (filesystem::exists(noReadFileName))
        {
            filesystem::remove(noWriteFileName);
            canRead= false;
            return;
        }
        canRead= true;
    }
    ~ReadStatus()
    {
        if (filesystem::exists(noWriteFileName))
            filesystem::remove(noWriteFileName);
    }
    inline bool OKToRead()
    {
        return canRead;
    }
};
Run Code Online (Sandbox Code Playgroud)

用法:

ReadStatus readStatus; //RAII FTW
    if ( ! readStatus.OKToRead())
        return;
Run Code Online (Sandbox Code Playgroud)

这是一个程序ofc,其他将有类似的类.想法是:1.检查其他程序是否创建了他的"我是所有者文件",如果它已经中断,则转到2. 2.创建我的"我是所有者"文件,再次检查其他程序是否创建了自己的,如果它已删除我的文件并打破其他,请转到3. 3.执行我的阅读,然后删除我的"我是所有者文件".

请注意,当它们都不读或写时很少出现,但问题是我仍然看到竞争条件的可能性很小,因为理论上其他程序可以检查我的锁文件的存在,看到没有一个,然后我创建了我的,其他程序创建了自己的程序,但在FS创建他的文件之前我再次检查,它不存在,然后发生灾难.这就是为什么我添加了一秒延迟,但作为CS书呆子,我发现让代码运行起来令人不安.Ofc我不希望这里的任何人给我写一个解决方案,但如果有人知道我可以使用的可靠代码的链接,我会很高兴.PS它必须是文件,因为我不是在编写整个项目,而是它是如何安排完成的.

PPS:访问数据文件不是读者,作者,读者,作家....它可以是读者,读者,作家,作家,作家,读者,作家....

PPS:其他进程不是用C++编写的:(因此提升是不可能的.

Dav*_*ven 8

在Unices上,传统的基于纯文件系统的锁定方法是使用带有mkdir()和的专用锁文件rmdir(),可以通过单个系统调用以原子方式创建和删除.您可以通过从不为锁的存在,明确地测试---而不是你总是尽量避免比赛采取了锁.所以:

lock:
    while mkdir(lockfile) fails
        sleep

unlock:
    rmdir(lockfile)
Run Code Online (Sandbox Code Playgroud)

我相信这甚至适用于NFS(这通常很糟糕).

但是,您可能还希望查看正确的文件锁定,这样可以更好地加载; 我在Linux上使用F_SETLK/F_UNLCK fcntl锁(注意这些与flock锁不同,尽管结构的名称).这允许您正确阻止,直到释放锁定.如果应用程序死亡,这些锁也会自动释放,这通常是一件好事.此外,这些将允许您直接锁定共享文件,而无需单独的锁定文件.这也适用于NFS.

Windows具有非常相似的文件锁定功能,并且它还具有易于使用的全局命名信号量,这些信号量非常便于进程之间的同步.