Когда я должен использовать блокировку видимости (приложение, сервер и т.д.) Против имени в ColdFusion?
Когда целесообразно использовать < cflock scope = "application" > или оно аналогично, в отличие от < cflock name= "foo" > ?
В частности, я заинтересован в использовании CFLock для защиты общих объектов в области приложений, сеансов или серверов, но мне также интересно узнать о различных применениях блокировки в ColdFusion.
Ответы
Ответ 1
Вы должны использовать при чтении и записи из вещей, которые могут измениться в области приложения. Например:
<cfquery name="application.myData">
select * from myTable
</cfquery>
Вам нужно заблокировать это с помощью type = "exclusive". Где бы ни использовалось application.myData, вам нужна блокировка type = "readonly". Исключением является метод Application.cfc OnApplicationStart, который блокирует себя. Аналогичным образом используйте ту же стратегию с областями сеанса и сервера.
Именованные блокировки дают вам больше контроля над вашей стратегией блокировки. Используйте названный cflock, когда вам нужно динамически блокировать команды. Например:
<cflock name="write_file_#session.user_type#" type="exclusive">
<cffile action="write" name="file_#session.user_type#" output="#content#" />
</cflock>
В этом примере пользователям разных типов разрешено записывать файл одновременно, но пользователи с тем же session.user_type должны ждать друг друга. Этот cflock помогает избежать конфликтов файлов.
Другая причина использования именованной блокировки - это если вы не знаете объем вашей текущей операции. Если вы находитесь в экземпляре cfc, как вы знаете, в какой области вы были созданы? Переменные? Сессия? Заявка? Хорошая инкапсуляция учит нас, что объекты ничего не знают, кроме того, что им сказали. Внутри CFC используйте именованный замок и назовите его после CFC, или CFC, и уникальную переменную экземпляра в зависимости от вашего варианта использования.
Ответ 2
Продолжая то, что @Mr. Нейт сказал, используйте блокировки всякий раз, когда вы обеспокоены условиями гонки. Например, вы можете заблокировать инициализацию сеанса, но не последующие чтения. Аналогично, вы можете заблокировать запись в область приложения, но не читаете.
Блокировка чтения намного менее полезна, поскольку CF6, который ввел потоковые области с видимыми потоками. В плохие старые дни, если вы не были осторожны, вы могли одновременно читать и писать один и тот же адрес памяти. Однако, поскольку CF стал Java-powered, это не проблема.
Именованные блокировки полезны, как он продемонстрировал, для блокировки всего, что не ограничено, например, чтение/запись файлов.
Ответ 3
основываясь на других предложениях здесь.
честно говоря, с момента появления cf8 и теперь, когда duplicate() может дублировать объекты, я бы использовал только блокировки областей при записи в область приложения, сеанса или сервера (кстати, запись в область сервера - нет в моей книге).
если вам нужно прочитать данные, я бы использовал duplicate(), чтобы сделать глубокую копию данных локальной переменной и избежать блокировки чтения. это предотвратит взаимоблокировки.
<cflock scope="application" timeout="5" type="exlusive">
<cfset application.data = {}>
<cfset application.data.firstname = "tony">
</cflock>
<cfset variables.firstname = duplicate(application.data.firstname)>
Ответ 4
Прекрасное время для использования именованной блокировки - это когда у вас есть "транзакция", которую вы хотите убедиться, что все происходит за один раз, например, обновление сразу нескольких таблиц в базе данных или когда вы просто хотите убедиться, что два пользователя не обновляют одну и ту же запись базы данных за раз или при чтении или записи в файл на сервере, который может иметь более одного пользователя одновременно, пытаясь получить к нему доступ.
Проще говоря, в любое время возникает ситуация, когда могут возникать проблемы, если два запроса пытались сделать одно и то же в одно и то же время, а затем помещать именованный замок вокруг него (или если он строго связан с областью сеанса, приложения или сервера, затем используйте фиксированную блокировку).
Бен Надель опубликовал запись в блоге, когда сказал:
"Как я вижу это, необходимо выполнить два условия, чтобы потребовать использование CFLock:
- Доступ к общему ресурсу или его обновление.
- Должна быть возможность состояния гонки, приводящая к НЕГАТИВНОму результату.
Вы даже можете вставлять теги CFLOCK, например, иметь именованный замок вокруг транзакции, а блокировки с привязкой к сеансу или приложениям внутри внутри, но делать это с осторожностью - если вы сделаете это неправильно, вы можете иметь ситуацию с "тупиком" где ни один запрос не может выполнить заблокированный раздел страницы, и все запросы к заблокированному разделу страницы могут быть заблокированы до тех пор, пока не будет тайм-аут. (В руководстве ColdFusion описаны лучшие методы вложенной блокировки.)
Ответ 5
Как правило, вы всегда должны использовать cflock для сеансов, приложений и серверов во время чтения или изменения этих vars вне Application.cfc, чтобы предотвратить условия гонки. Вот статья, которая может быть полезна:
http://www.horwith.com/index.cfm/2008/4/28/cflock-explained
Изменить: Чтобы ответить на вопрос о сфере видимости, я всегда использую <cflock scope="application">
(например) при взаимодействии с общими ресурсами.
Ответ 6
Это пример из документации ColdFusion 8, в которой используется переменная страницы для создания "локального флага", который можно прочитать без блокировки, чтобы узнать, были ли инициализированы переменные приложения.
То, что это касается адреса, - это то, что нам нужно условно исключить исключительную блокировку, потому что ее запуск при каждой загрузке страницы может создать узкие места из-за блокировки, занимающей больше времени обработки.
Я не знаю, появились ли с тех пор лучшие методы, но я полагаю, что я все равно отправлю его сюда. Документы ColdFusion часто не обеспечивают хороший код, поэтому мне интересно узнать, может ли кто-нибудь увидеть, как это можно улучшить.
- Я могу поместить локальный флаг в область запроса, чтобы он был доступен даже в пользовательских тегах и т.д. Однако он действительно нужен только в app.cfm, поэтому, возможно, это лишнее.
- Я также удалял isDefined() в пользу structKeyExists(), так что ему не нужно было бы перебирать все области.
- Я также использовал бы скотч-нотацию для установки переменных, чтобы сохранить капитализацию (например, приложение ['myDsn'] = "orders" ). Это также облегчает определение записи переменных, которые немного важнее, чем чтение переменных. (Это только мое предпочтение)
Источник: http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=sharedVars_18.html
<!--- Initialize local flag to false. --->
<cfset app_is_initialized = False>
<!--- Get a readonly lock --->
<cflock scope="application" type="readonly">
<!--- read init flag and store it in local variable --->
<cfset app_is_initialized = IsDefined("APPLICATION.initialized")>
</cflock>
<!--- Check the local flag --->
<cfif not app_is_initialized >
<!--- Not initialized yet, get exclusive lock to write scope --->
<cflock scope="application" type="exclusive">
<!--- Check nonlocal flag since multiple requests could get to the
exclusive lock --->
<cfif not IsDefined("APPLICATION.initialized") >
<!--- Do initializations --->
<cfset APPLICATION.varible1 = someValue >
...
<!--- Set the Application scope initialization flag --->
<cfset APPLICATION.initialized = "yes">
</cfif>
</cflock>
</cfif>