我正在寻找一个简单的已经实现的解决方案,用于在MATLAB中原子地创建文件锁。
类似的东西:
file_lock('create', 'mylockfile'); %this will block until it creates the lock file.
file_lock('remove', 'mylockfile'); %this will remove the lock file:
已经多次询问过这个问题,提出了一些解决方案的想法(例如使用Java FileLock
),
但我没有找到一个简单的已经实施的解决方案。
你知道这样一个实施的解决方案吗?
注意:
答案 0 :(得分:5)
我已经找到了一个非常简单的解决方案,可以将来自多个工作线程的错误/日志记录消息组合到一个文件中。每次我想写入该文件时,我首先将输出写入线程自己的临时文件。接下来,我使用flock将该临时文件附加到“master”日志文件中。在这里省略一些细节,这个想法是:
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手册页,但上面的调用是在日志文件上获取一个eXclusive锁,在锁下运行提供的Command,然后释放它。
这显然只有你在一个拥有flock的系统(Linux / OS X,并且只有某些类型的文件系统)并且你正在做一些可以通过命令行完成的事情时才有效,但是我打赌这是一个非常常见的用例。
答案 1 :(得分:1)
根据您使用的Java版本,这可能会起作用(翻译自:http://www.javabeat.net/2007/10/locking-files-using-java/)
classdef FileLock < handle
properties (Access = private)
fileLock = []
file
end
methods
function this = FileLock(filename)
this.file = java.io.RandomAccessFile(filename,'rw');
fileChannel = this.file.getChannel();
this.fileLock = fileChannel.tryLock();
end
function val = hasLock(this)
if ~isempty(this.fileLock) && this.fileLock.isValid()
val = true;
else
val = false;
end
end
function delete(this)
this.release();
end
function release(this)
if this.hasLock
this.fileLock.release();
end
this.file.close
end
end
end
用法是:
lock = FileLock('my_lock_file');
if lock.hasLock
%// do something here
else
%// I guess not
end
%// Manually release the lock, or just delete (or let matlab clean it up)
我喜欢IO的obj包装模式,因此即使在例外情况下也会发布
编辑:必须保留文件引用并手动关闭,否则您将无法对其进行编辑。这意味着我认为这段代码对纯锁文件非常有用。
答案 2 :(得分:0)
写入新文件,然后重命名。重命名是一种原子操作,所有新内容将立即显示。
答案 3 :(得分:0)
最后,我根据两个连续测试(movefile,并验证移动文件的内容)进行了一次实现。
写得不是很好,但现在对我来说很有用。
+++++ file_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
++++++++++++++++++++++++++++++++++++++++++
答案 4 :(得分:0)
如果您只需要在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