【发布时间】:2010-10-03 02:34:46
【问题描述】:
事情是这样的:我有两个应用程序,用 C++ 编写并在两台具有不同操作系统(一台 Linux 和一台 Windows)的机器上运行。其中一个过程负责更新 NAS(网络附加存储)上的 XML 文件,而另一个则读取该文件。
是否可以同步这两个进程以避免在修改文件的同时读取文件?
【问题讨论】:
标签: c++ concurrency synchronization mutex nas
事情是这样的:我有两个应用程序,用 C++ 编写并在两台具有不同操作系统(一台 Linux 和一台 Windows)的机器上运行。其中一个过程负责更新 NAS(网络附加存储)上的 XML 文件,而另一个则读取该文件。
是否可以同步这两个进程以避免在修改文件的同时读取文件?
【问题讨论】:
标签: c++ concurrency synchronization mutex nas
您可以在执行写入之前创建的服务器上创建一个锁定文件,等待然后写入并在完成时删除。在读取文件之前让读取进程检查令牌。
编辑:要解决 cmets,您可以实现双重检查锁定类型模式。让读者和作者都有一个锁定文件并在工作之前仔细检查,例如:
Reader:检查写锁文件,创建读锁文件,检查写锁文件,如果存在则删除读文件并中止。
Writer:检查读锁文件,创建写锁文件,检查读锁文件,如果存在则删除写锁文件并中止。
这将阻止您的进程相互践踏,但可能会发生潜在的竞争条件,因为您可能会同时检查、创建和重新检查两个进程,但这不会导致数据以不一致的状态读取,但会导致读取和写入进程在您指定的延迟内中止
【讨论】:
谢谢大家的回答。
最后我们设法解决了我们的问题,不是通过使用操作系统的锁定命令(因为我们不确定它们是否会正确传播到 NAS 头的操作系统),而是通过创建锁定目录而不是锁定文件。目录创建是原子操作,如果文件夹已经存在则返回错误值。因此,我们不必在获取锁之前检查它是否存在,这两个操作都是一步完成的。
【讨论】:
好的,您需要某种形式的锁定机制来控制访问。
大多数 *nix 文件系统都提供此功能。我怀疑它在 Windows 文件系统上也可用(因为 perl 使用了这种机制),但它可能有另一个名称。
看一下flock()。
这是一种文件锁定机制。它是一种建议锁,因此它实际上不会锁定文件并阻止使用,但它提供了一种标记文件的机制。如果两个应用程序都使用该机制,那么您可以控制对文件的访问。
flock() 提供共享锁(或读锁)和排他锁(或写锁)。 flock 将阻塞您的线程(以非忙碌方式),直到用户解锁文件(它还提供非阻塞检查,因此您可以在等待时做其他事情)。
查看手册页第 2 节中的羊群。
int flock(int fd, int operation);
Flock() applies or removes an advisory lock on the file associated with the file
descriptor fd. A lock is applied by specifying an operation parameter that is
one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB. To unlock an
existing lock operation should be LOCK_UN.
【讨论】:
如果文件位于 NFS 共享上,您可以使用 fcntl(2) 锁定文件。检查Linux NFS FAQ 中的问题D10。我对 Windows API 的经验很少,但据我所知,它们具有良好的 POSIX 支持,因此只要它们支持 POSIX.1-2001,您就应该能够使用 fcntl。
如果您使用不同的协议(即 AFS 或 SMB)访问文件,也许您可以设置一个简单的同步服务器,通过 IPC 接口管理锁?
【讨论】:
是否可以从文件切换到数据库?
DBMS 可以很好地管理这种类型的并发性。它不需要昂贵或难以安装。 MySql、Postgress 或 JavaDB 都可以以很少或没有成本优雅地处理这个问题。
如果数据库选项失败,我会让写入过程写入“隐藏”文件名,如“.updateinprogress.xml”,并在更新完成后重命名文件。在大多数系统上,“mv”或“ren”是一个原子操作,因此读取过程要么选择旧文件,要么选择新文件,但永远不会写一半。
【讨论】: