Блокировка здесь кажется разумной, но это не то место, и вы не блокируете доступ к файлу исключительно. Вы должны заблокировать всю транзакцию, то есть заблокировать прямо перед получением 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 секунд, пока семафор не завершится). дать ход, или в противном случае просто забыть об этом и выйти). После завершения операции копирования в первом потоке семафор прекратит работу и проверит очередь. Если другие потоки в это время были поставлены в очередь, следующий поток в очереди возобновит выполнение, очистится и повторится.
Эксклюзивная блокировка гарантирует, что поток никогда не увидит незавершенное состояние файла (= получение файла, который собирается скопировать другим потоком).
16.02.2019