我应该<cflock>一个<cffile action =“ COPY” ... =“”>吗?

时间:2019-02-16 05:15:36

标签: coldfusion coldfusion-9

查看一些偶尔会超时的旧代码,我在CFLOOP内运行的CFFILE COPY周围遇到了这个CFLOCK。

这种使用CFFLOCK有意义还是看起来必要?该文件将从一个位置复制到一个新创建的文件夹,该文件夹本身又被压缩以供将来下载。

起初,我只是想增加锁的超时时间,但后来我开始盯着它,想知道这是否是一个错误。

<cfloop query="LOCAL.qDocsZip">
<cflock name="copyFileLock" timeout="3600" type="readonly">
<cffile action="copy"
source="#ExpandPath(LOCAL.qDocsZip.file_location)#"     
destination="#LOCAL.zip_new_path#/#LOCAL.qDocsZip.original_file_name#">
</cflock>
</cfloop>

1 个答案:

答案 0 :(得分:2)

在这里锁定似乎是合理的,但这不是正确的选择,您也不能独占地锁定文件访问。您应该锁定整个交易,即在获取LOCAL.qDocsZip之前锁定。这样,您可以确保要复制的文件仅由单个线程触摸,并且不会与另一个线程并发。请注意:cflock是JVM特定的信号量,因此它不能保证系统级的事务安全,例如:如果您还有其他程序可以并行访问文件。

这是它的外观:

<!--- only one thread at a time can execute the code within this lock (exclusive named lock) --->
<cflock name="copyFileLock" timeout="3600" type="exclusive">

    <!--- fetch files to copy in this transaction --->
    <cfquery name="LOCAL.qDocsZip" ...>
        ...
    </cfquery>

    <!--- copy all the files --->
    <cfloop query="LOCAL.qDocsZip">
        <cffile action="copy" ...>
    </cfloop>

</cflock>

(如果您的代码片段中不仅仅包含一些错误处理,那么您可能还应该添加一些错误处理。)

说明

每个线程都将在cflock处停止,并询问信号量copyFileLock是否当前正在“运行”。如果没有,线程将继续,获取文件并复制它们。在整个复制过程中(信号量正在“运行”),遇到cflock的每个其他线程都将排队,因此暂停执行并等待信号量(在您的情况下,每个排队的线程将等待在3600秒后,信号灯会发出“ go”信号,否则请忽略它并退出)。在第一个线程上完成复制操作后,信号灯将停止“运行”并检查队列。如果同时有其他线程在排队,则队列中的下一个线程将恢复执行,冲洗并重复。

排他锁将确保线程永远不会“看到”不完整的文件状态(=获取要由另一个线程复制的文件)。