R中的文件锁定

问题描述 投票:6回答:1

短版

我将如何阻止访问文件,直到返回一个既涉及文件读写过程的特定功能,又返回该文件?


用例

我经常想创建某种中央注册表,并且从该注册表中读取和写入该注册表可能涉及多个R进程(以“穷人并行化”设置的形式,其中不同进程彼此独立运行,但关于注册表访问)。

我会希望在开发过程的早期就依赖于任何DBMS,例如SQLitePostgreSQLMongoDB等。即使我以后可能使用DBMS,基于文件系统的解决方案仍可能是方便的后备选项。因此,我很好奇如何通过基本R功能实现它。

[我知道与DBMS解决方案相比,以并行设置对文件系统进行大量读写不是很有效。

我正在MS Windows 8.1(64位)上运行

我想加深了解的内容

[当两个或多个R进程尝试同时写入或读取文件时,实际上会发生什么? OS是否会自动找出“访问顺序”,并且“进入第二个”进程等待还是由于文件访问可能被第一个进程阻止而触发错误?如何防止第二个进程返回错误,而是“等一下”直到轮到他了?

进程的共享工作空间

rredis软件包之外:MS Windows上是否还有其他共享内存选项?

插图

注册表文件的路径:

path_registry <- file.path(tempdir(), "registry.rdata")

注册事件的示例函数:

registerEvent <- function(
    id=gsub("-| |:", "", Sys.time()), 
    values, 
    path_registry
) {
    if (!file.exists(path_registry)) {
        registry <- new.env()
        save(registry, file=path_registry)
    } else {
        load(path_registry)
    }

    message("Simulated additional runtime between reading and writing (5 seconds)")
    Sys.sleep(5)

    if (!exists(id, envir=registry, inherits=FALSE)) {
        assign(id, values, registry)
        save(registry, file=path_registry)
        message(sprintf("Registering with ID %s", id))
        out <- TRUE
    } else {
        message(sprintf("ID %s already registered", id))
        out <- FALSE
    }
    out
}

已注册的示例内容:

x <- new.env()
x$a <- TRUE
x$b <- letters[1:5]

请注意,内容通常是“嵌套的”,即RDBMS无论如何都不会真正“有用”,或者至少在写入数据库之前会涉及一些标准化步骤。这就是为什么我更喜欢environment(可以使用唯一变量ID和传递引用)而不是list的原因,如果确实有人使用了真正的DBMS,那么我宁愿转向NoSQL方法,例如MongoDB ]。

注册周期:

实际的调用可能会分散在不同的进程中,因此可能会有并发访问尝试。

我想让其他进程/调用“等待”,直到完成registerEvent读写周期之后再执行其读写周期(无触发错误)。

registerEvent(values=list(x_1=x, x_2=x), path_registry=path_registry)
registerEvent(values=list(x_1=x, x_2=x), path_registry=path_registry)
registerEvent(id="abcd", values=list(x_1=x, x_2=x), 
    path_registry=path_registry)
registerEvent(id="abcd", values=list(x_1=x, x_2=x), 
    path_registry=path_registry)

检查注册表内容:

load(path_registry)
ls(registry)
r filesystems locking read-write
1个回答
1
投票

请参阅filelock R软件包,自2018年以来可用。它是跨平台的。我在Windows上使用它,但未发现任何问题。

请务必阅读文档。

?filelock::lock

尽管文档建议保留锁文件,但在多进程环境中的函数出口上删除它没有问题:

on.exit({filelock::unlock(lock); file.remove(path.lock)})
© www.soinside.com 2019 - 2024. All rights reserved.