我有一种情况,其中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;
}
};
用法:
ReadStatus readStatus; //RAII FTW
if ( ! readStatus.OKToRead())
return;
这是针对一个程序ofc,其他将有类似的类。 想法是: 1.检查其他程序是否创建了他的“我是所有者文件”,如果它已经中断,则转到2。 2.创建我的“我是所有者”文件,再次检查其他程序是否创建了自己的文件,如果它已删除我的文件并且中断则返回3。 3.做我的阅读,然后删除我的“我是所有者文件”。
请注意,当他们不读或写时很少出现,但问题是我仍然看到竞争条件的可能性很小,因为理论上其他程序可以检查我的锁文件是否存在,看到没有一,然后我创建我的,其他程序创建自己的,但在FS创建他的文件之前我再次检查,它不在那里,然后发生灾难。这就是为什么我添加了一秒延迟,但作为CS书呆子,我发现让代码运行起来令人不安。 Ofc我不希望这里的任何人给我写一个解决方案,但如果有人知道我可以使用的可靠代码的链接,我会很高兴。 附:它必须是文件,因为我不是在编写整个项目,而是它是如何安排完成的。
P.P.S。:访问数据文件不是读者,作家,读者,作家....它可以是读者,读者,作家,作家,作家,读者,作家....
P.P.S:其他过程不是用C ++编写的:(因此,提升是不可能的。
答案 0 :(得分:7)
On Unices传统的基于纯文件系统的锁定方法是使用mkdir()
和rmdir()
的专用锁文件,可以通过单个系统调用以原子方式创建和删除。你从不明确地测试锁的存在来避免竞争 - 而是你总是试图接受锁。所以:
lock:
while mkdir(lockfile) fails
sleep
unlock:
rmdir(lockfile)
我相信这甚至适用于NFS(这通常很糟糕)。
但是,您可能还想查看正确的文件锁定,这样可以更好地加载;我在Linux上使用F_SETLK/F_UNLCK fcntl locks(注意这些与flock锁不同,尽管结构的名称)。这允许您正确阻止,直到释放锁定。如果应用程序死亡,这些锁也会自动释放,这通常是一件好事。此外,这些将允许您直接锁定共享文件,而无需单独的锁定文件。这也适用于NFS。
Windows具有非常相似的文件锁定功能,并且它还具有易于使用的全局命名信号量,非常便于进程之间的同步。
答案 1 :(得分:3)
就我所见,你无法可靠地将文件用作多个进程的锁。问题是,当您在一个线程中创建文件时,您可能会得到一个中断,并且操作系统会切换到另一个进程,因为I / O需要很长时间。删除锁定文件也是如此。
如果可以,请查看同步机制部分下的Boost.Interprocess。
答案 2 :(得分:1)
虽然我一般反对进行API调用,这些API调用可以从构造函数/析构函数抛出(请参阅boost::filesystem::remove
上的文档)或者在没有catch块的情况下进行抛出调用,但这并不是你所要求的。< / p>
如果这是用于Windows,您可以查看Overlapped IO库。否则,您是否考虑过使用shared memory between the processes?
编辑:刚看到其他进程是Java。您仍然可以创建一个可以在进程之间共享的命名互斥锁,并使用它来创建围绕文件IO位的锁,这样它们就必须轮流写入。对不起我不懂Java所以我不知道这是否比共享内存更可行。