多线程安全的多文件写入

3
我有一个守护进程,接受套接字连接并读取或写入一组动态文件,具体取决于连接的性质。由于我的守护进程是多线程的,存在同一文件可能被多个线程写入的可能性。因为我的文件列表是动态的而不是固定的,所以我不确定如何防止一个线程与另一个线程发生冲突。出于性能考虑,我希望线程在同时写入不同文件的情况下工作,但不能同时写入同一文件。
其他问题建议使用互斥锁,但我不太清楚互斥锁在这种情况下如何帮助 - 文件列表是动态的且仅已知于该线程。
在这种情况下,使用文件锁是否合适?如果是这样,如何以线程安全的方式实现文件锁定?

无论如何,您需要对每个文件进行互斥访问 -- 您可以使用Matthew PK的“文件代理”概念来实现,甚至只需使用从(绝对)文件名到互斥体的哈希表即可(显然,哈希表本身的修改也应该使用互斥体进行序列化)。 - Conrad Meyer
1
@Conrad Meyer:对 st_dev / st_ino 组合进行哈希可能比文件名更好,因为与实际唯一标识文件的文件名不同。 - caf
这就是了。一个全局且独特的东西。但是,如果他或她的系统依赖于不同的inode具有相同的文件名,那么它可能已经损坏了。 - Conrad Meyer
3个回答

2

flock可以正常工作。它不会锁定文件描述符,而是锁定实际文件。

已经被排他性flock的文件不能再被另一个进程或线程排他性地锁定。这将破坏锁的整个目的。

需要注意的是,这些锁是咨询性的。一个不使用flock的进程可以愉快地覆盖该文件,即使另一个进程已经排他性地flock了它。


1
我会使用事件代理模式。每个套接字线程触发一个事件(具有文件的参数),然后中央文件代理处理该事件,并具有共享的正在编写的文件集合。
如果无法将文件写入,请决定您想要做什么...否则报告成功。
多个监听器,一个中央文件锁集合,多个编写者。

1

我不能说这是“最佳”解决方案,但我建议像这样做:

维护一个包含两个内容的结构体的链表:

  1. 文件名
  2. 与该文件相关联的条件等待变量。

流程A。当守护程序接收到请求时,互斥锁定列表并检查文件名是否在列表中。如果不在列表中,则添加一个新条目到链表中,并为其他线程使用创建一个新的条件等待变量。释放互斥锁。执行文件操作。完成后,锁定链表并删除该文件的结构体条目,然后通过等待对象向其他线程发出信号。

流程B。如果针对同一文件的请求进入,它将锁定列表并查找列表中包含的文件名。如果在列表中,则获取等待变量并等待它。当线程被通知时,获取列表上的锁并查看文件是否在列表中(可能另一个线程在你之前锁定了文件名)。如果没有,请按照流程A进行。如果有,请获取新结构体中的等待变量并再次等待直到被通知,然后再次按照上述步骤进行。


我会对上述内容做出的一个改变是使用哈希表来存储结构体,而不是链表,正如Conrad在原问题的评论中所说;这将极大地提高实际检查操作的效率,特别是对于同时打开大量文件的情况。 - wibarr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接