Когда я должен использовать блокировку видимости (приложение, сервер и т.д.) Против имени в 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>