Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 在MATLAB中自动创建文件锁(文件互斥)_File_Matlab_Concurrency_Locking_Mutex - Fatal编程技术网

File 在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), 但是我没有找到

我正在寻找一个简单的已经实现的解决方案,用于在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
), 但是我没有找到一个简单的已经实现的解决方案

您知道这样一个已实施的解决方案吗

注:


    • 写入新文件,然后重命名。重命名是一个原子操作,所有新内容将立即可见。

      最后,我基于两个连续的测试(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