使用文件锁进行进程间同步

文件锁的作用主要是控制多个进程间对同一个文件进行读写并发、数据读写完整性的控制。

假如有这样的一个问题,看是否可以使用文件锁进行解决。问题可以这样来描述,有N个进程需要同时处理M个目录下面的文件,要求将M个目录分配给N个进程实例,然后每个进程可以处理单个目录下面的所有文件。那么,如何让N个进程自行分配M个目录呢?

使用文件锁的总体思路

可以使用文件锁来达到任务自动分配的目的。整体思路是这样子的

  1. 在M个目录同级创建一个共享文件f,文件f中存储了这M个目录的所有信息。
  2. N个进程通过文件锁的方式去争抢文件f,当争抢到后从f中取出一个目录信息,从文件中删除该目录,然后释放文件锁,去处理目录下面的文件。
  3. 重复步骤2,直接文件f里的所有任务都分配完毕,文件f大小为0。
  4. 删除文件f。

在第一步中,文件f的创建也是由N个进程通过争抢方式来创建的,

一旦文件f确实创建了,并且保存了所有要分配的M个目录信息,那么接下来,N个进程就可以使用文件锁的方式争抢M个目录了。直到所有目录都争抢完毕,任务处理完成后,某个进程将文件f删除了即可。

问题1:中间文件f的管理

在实际的生产环境中,中间文件f是要进行管理的,即创建、使用完成之后需要删除。其中,最关键的是删除操作。文件的删除操作需要考虑如下几个场景:

在上面三种场景下,处理删除文件的策略各有不同,第一种情况是非异常情况可以不用太关心。第二种情况下,事务回滚情况下,文件的删除要依赖于事务回滚机制进行,否则就需要完善事务回滚的机制了。第三种情况中,可以在进程重启过程中处理这个问题。

问题2:设计方案的缺陷

使用文件锁处理任务分配这类问题,如果不考虑性能的话,从功能完善上讲需要慎重考虑由于文件f删除而带来的问题。简单来讲,该方案使用文件锁的一个基本前提条件是, N个进程可以同时探测到共享文件f的存在。这个前提条件一旦破坏,那么设计方案就会有严重的问题。考虑一个极端的情况,描述如下(假设总共有3个进程):

可以看到,在极端情况下,任务分配会出现重复N次的问题。其实,中间文件f的删除引入的问题不止如此,在实际的编码过程中,对于文件读写IO的返回值时刻要关注“文件可能被删除的问题”。那么,从问题的界定来讲,就会引入另一个问题:文件IO的错误是由于预期中的删除操作引起的,还是由于磁盘IO本身确定发生了错误。这就得再增加额外的手段,先确定是否发生了IO问题。

小结

文件锁应用于进程间同步时,文件的删除操作会引入许多问题,其中一个问题是致命的、无解的。所以,文件锁并不适用于这种场景的解决方案。可以采取两种方法来解决:

  1. 使用持久化的文件,不对文件进行删除
  2. 使用替代方案,避免引入中间文件操作

参考文章

Table of Contents