File 在MATLAB中自动创建文件锁(文件互斥)
我正在寻找一个简单的已经实现的解决方案,用于在MATLAB中以原子方式创建文件锁 比如:File 在MATLAB中自动创建文件锁(文件互斥),file,matlab,concurrency,locking,mutex,File,Matlab,Concurrency,Locking,Mutex,我正在寻找一个简单的已经实现的解决方案,用于在MATLAB中以原子方式创建文件锁 比如: file_lock('create', 'mylockfile'); %this will block until it creates the lock file. file_lock('remove', 'mylockfile'); %this will remove the lock file: 这个问题已经被问了好几次,并提出了一些解决方案想法(例如使用JavaFileLock), 但是我没有找到
file_lock('create', 'mylockfile'); %this will block until it creates the lock file.
file_lock('remove', 'mylockfile'); %this will remove the lock file:
这个问题已经被问了好几次,并提出了一些解决方案想法(例如使用JavaFileLock
),
但是我没有找到一个简单的已经实现的解决方案
您知道这样一个已实施的解决方案吗
注:
- 写入新文件,然后重命名。重命名是一个原子操作,所有新内容将立即可见。最后,我基于两个连续的测试(movefile和验证移动文件的内容)执行了一个实现
写得不太好,但现在对我来说很有效
+++++文件_lock.m++++++++++++++++++++++++
function file_lock(op, filename)
%this will block until it creates the lock file:
%file_lock('create', 'mylockfile')
%
%this will remove the lock file:
%file_lock('remove', 'mylockfile')
% todo: verify that there are no bugs
filename = [filename '.mat'];
if isequal(op, 'create')
id = [tempname() '.mat']
while true
save(id, 'id');
success = fileattrib(id, '-w');
if success == 0; error('fileattrib'); end
while true
if exist(filename, 'file'); %first test
fprintf('file lock exists(1). waiting...\n');
pause(1);
continue;
end
status = movefile(id, filename); %second test
if status == 1; break; end
fprintf('file lock exists(2). waiting...\n');
pause(1);
end
temp = load(filename, 'id'); % third test.
if isequal(id, temp.id); break; end
fprintf('file lock exists(3). waiting...\n');
pause(1)
end
elseif isequal(op, 'remove')
%delete(filename);
execute_rs(@() delete(filename));
else
error('invalid op');
end
function execute_rs(f)
while true
try
lastwarn('');
f();
if ~isequal(lastwarn, ''); error(lastwarn); end %such as: Warning: File not found or permission denied
break;
catch exception
fprintf('Error: %s\n.Retrying...\n', exception.message);
pause(.5);
end
end
++++++++++++++++++++++++++++++++++++++++++我找到了一个非常简单的解决方案,可以将来自多个工作线程的错误/日志消息合并到一个文件中。每次我想写入该文件时,我首先将输出写入线程自己的临时文件。接下来,我使用flock将该临时文件附加到“主”日志文件中。这里略过一些细节,想法是:
function file_lock(op, filename)
%this will block until it creates the lock file:
%file_lock('create', 'mylockfile')
%
%this will remove the lock file:
%file_lock('remove', 'mylockfile')
% todo: verify that there are no bugs
filename = [filename '.mat'];
if isequal(op, 'create')
id = [tempname() '.mat']
while true
save(id, 'id');
success = fileattrib(id, '-w');
if success == 0; error('fileattrib'); end
while true
if exist(filename, 'file'); %first test
fprintf('file lock exists(1). waiting...\n');
pause(1);
continue;
end
status = movefile(id, filename); %second test
if status == 1; break; end
fprintf('file lock exists(2). waiting...\n');
pause(1);
end
temp = load(filename, 'id'); % third test.
if isequal(id, temp.id); break; end
fprintf('file lock exists(3). waiting...\n');
pause(1)
end
elseif isequal(op, 'remove')
%delete(filename);
execute_rs(@() delete(filename));
else
error('invalid op');
end
function execute_rs(f)
while true
try
lastwarn('');
f();
if ~isequal(lastwarn, ''); error(lastwarn); end %such as: Warning: File not found or permission denied
break;
catch exception
fprintf('Error: %s\n.Retrying...\n', exception.message);
pause(.5);
end
end
fid=fopen(threadtemp, 'w');
fprintf(fid, 'Error message goes here');
fclose(fid);
runme = sprintf('flock -x %s -c ''cat %s >> %s''', LOGFILE, threadtemp, LOGFILE);
system(runme);
有关详细信息,请参见flock手册页,但上面的调用获取日志文件上的独占锁,在锁下运行提供的命令,然后释放它
这显然只适用于具有flock(Linux/OS X,并且仅适用于某些类型的文件系统)的系统,并且您正在做一些可以从命令行完成的事情,但我敢打赌这是一个非常常见的用例。根据您使用的Java版本,这可能会起作用(翻译自:) 我喜欢IO的obj包装模式,这样即使在异常情况下也可以释放
编辑:必须保留文件引用并手动关闭,否则您将无法编辑此文件。这意味着这段代码只对纯锁文件有用。如果您只需要在OS X和Linux(而不是Windows)上运行,您可以使用以下代码:
pathLock='/tmp/test.lock'
% Try to create and lock this file.
% In my case I use -r 0 to avoid retrying
% You could use -r -1 to retry forever, or for a particular amount of time,
% etc, see `man lockfile` for details.
if ~system(sprintf('lockfile -r 0 %s',pathLock))
% We succeeded, so perform some task which needs to be serialized.
% runSerializedTask()
% Now remove the lockfile
system(sprintf('rm -f %s',pathLock));
end
这个想法也是在中提出的,但事实证明unix的重命名不是原子的(首先它删除dest文件,然后重命名源文件),matlab在unix中使用unix的重命名,所以这个解决方案也不起作用。只需阅读该线程。大家一致认为MatLab的
movefile
命令不仅仅是一个rename
调用,因此movefile
不是原子的。SUS非常清楚地表明,rename
在unix上是原子的(当然,如果您使用的是不符合规范的类unix克隆,情况就不同了)。如果一个工作人员在movefile
之前被打断,我想你会遇到问题。我不想成为一个扫兴的人,但这在一般情况下是极难纠正的,尤其是对于网络文件。文件锁定高度依赖于系统。没有一个简单的、已经实现的解决方案不会被打破。(写一些“似乎大部分都能工作”的东西并不难;写一些不会在生产中失败的东西也不难。)让我们退一步:你想同步访问什么?是文件内容,还是文件代表其他资源?你的目标是什么平台?您需要排除的“正确”程度如何?只是想知道,为什么要执行创建临时文件的步骤?为什么不使用类似系统的东西('flock-x日志文件-c''echo errormessage>>日志文件“”)?谢谢你,没有什么特别的原因——你的方法应该很有效。我想我的一些原始函数需要登录到文件名,所以这让我可以在不做任何更改的情况下使用它们,但我想这基本上是退化的。唯一真正的诀窍是使用system()调用flock。请注意,对于这样的方法在网络文件系统上是否安全,有很多讨论。lockfile手册页说它是“抗NFS的”,但我不确定这是什么意思:)或者它是否涵盖了所有与此相关的问题(它们变得相当复杂!)
pathLock='/tmp/test.lock'
% Try to create and lock this file.
% In my case I use -r 0 to avoid retrying
% You could use -r -1 to retry forever, or for a particular amount of time,
% etc, see `man lockfile` for details.
if ~system(sprintf('lockfile -r 0 %s',pathLock))
% We succeeded, so perform some task which needs to be serialized.
% runSerializedTask()
% Now remove the lockfile
system(sprintf('rm -f %s',pathLock));
end