查看一些偶尔会超时的旧代码,我在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>
答案 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”信号,否则请忽略它并退出)。在第一个线程上完成复制操作后,信号灯将停止“运行”并检查队列。如果同时有其他线程在排队,则队列中的下一个线程将恢复执行,冲洗并重复。
排他锁将确保线程永远不会“看到”不完整的文件状态(=获取要由另一个线程复制的文件)。