是job.内存线程安全的写入?



可以工作。内存用于以线程安全的方式跨多个进程写入公共缓存。在什么情况下(如果有的话)会失败或导致错误?

库首先写入临时文件,然后将临时文件移动到目标。源代码:

def _concurrency_safe_write(self, to_write, filename, write_func):
"""Writes an object into a file in a concurrency-safe way."""
temporary_filename = concurrency_safe_write(to_write,
filename, write_func)
self._move_item(temporary_filename, filename)
在同一个操作系统的进程中,写临时文件似乎是安全的,因为它在文件名中包含了pid。此外,它在同一进程中的线程之间似乎是安全的,因为它包含线程id。来源:
def concurrency_safe_write(object_to_write, filename, write_func):
"""Writes an object into a unique file in a concurrency-safe way."""
thread_id = id(threading.current_thread())
temporary_filename = '{}.thread-{}-pid-{}'.format(
filename, thread_id, os.getpid())
write_func(object_to_write, temporary_filename)
return temporary_filename

将临时文件移动到目标在Windows上显示问题。来源:

if os.name == 'nt':
# https://github.com/joblib/joblib/issues/540
access_denied_errors = (5, 13)
from os import replace
def concurrency_safe_rename(src, dst):
"""Renames ``src`` into ``dst`` overwriting ``dst`` if it exists.
On Windows os.replace can yield permission errors if executed by two
different processes.
"""
max_sleep_time = 1
total_sleep_time = 0
sleep_time = 0.001
while total_sleep_time < max_sleep_time:
try:
replace(src, dst)
break
except Exception as exc:
if getattr(exc, 'winerror', None) in access_denied_errors:
time.sleep(sleep_time)
total_sleep_time += sleep_time
sleep_time *= 2
else:
raise
else:
raise
else:
from os import replace as concurrency_safe_rename  # noqa

从这个源代码中可以看到,在Windows上,由于访问拒绝错误,在总时间1秒内无法将临时文件移动到目标,并且使用指数回退重试,它可能会失败。

相同的源代码有一个指向问题#540的链接,该问题描述了Windows错误,并以注释关闭:

由#541修复(希望)。

,(希望)";在评论中,作者似乎不能保证修复是最终的,但这个问题没有重新打开,所以它可能不会再发生。

对于其他操作系统,没有特殊的逻辑或重试,只使用标准的os.replace()。描述中提到了"可能失败"的情况。而且它将是一个原子操作

src文件或目录重命名为dst。如果dst是目录,则会引发OSError。如果dst存在并且是一个文件,如果用户有权限,它将被静默替换。如果srcdst在不同的文件系统上,则操作可能失败。如果成功,重命名将是一个原子操作(这是POSIX的要求)。

如果没有人在更改目标目录中的权限,则不应该太担心此操作失败的可能性。"如果srcdst在不同的文件系统上"的场景;似乎不可行,因为源路径(临时文件)只是通过向目标路径添加后缀来构建的,所以它们应该在同一个目录中。

关于rename的原子性的其他问题:

  • rename()是原子的吗?
  • mv是原子在我的fs?
  • 标准要求重命名是原子的吗?

最新更新