在MATLAB中原子地创建文件锁(文件互斥)

时间:2010-08-10 16:48:03

标签: 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:

已经多次询问过这个问题,提出了一些解决方案的想法(例如使用Java FileLock), 但我没有找到一个简单的已经实施的解决方案。

你知道这样一个实施的解决方案吗?

注意:

5 个答案:

答案 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