在一些像这样的asp 教程中,我观察到以下模式:
应用程序锁
'对应用程序对象做一些事情
应用程序.解锁
但是,由于网页可以有多个实例,因此存在明显的并发问题。所以我的问题如下:
如果一个页面在对象已经被锁定时试图锁定怎么办?
有没有办法检测应用程序对象是否被锁定?
只在未锁定的应用程序对象上工作会更好还是会产生其他后果?
如果只有一个动作涉及应用程序对象怎么办?〜在这种情况下有理由锁定/解锁吗?
在一些像这样的asp 教程中,我观察到以下模式:
应用程序锁
'对应用程序对象做一些事情
应用程序.解锁
但是,由于网页可以有多个实例,因此存在明显的并发问题。所以我的问题如下:
如果一个页面在对象已经被锁定时试图锁定怎么办?
有没有办法检测应用程序对象是否被锁定?
只在未锁定的应用程序对象上工作会更好还是会产生其他后果?
如果只有一个动作涉及应用程序对象怎么办?〜在这种情况下有理由锁定/解锁吗?
从MSDN 文档:
该Lock
方法阻止其他客户端修改存储在应用程序对象中的变量,确保一次只有一个客户端可以更改或访问应用程序变量。
如果您不显式调用该方法,则服务器会在 .asp 文件结束或超时Application.Unlock
时解锁锁定的 Application 对象。
应用程序对象上的锁定会持续很短的时间,因为当页面完成处理或超时时应用程序对象被解锁。
如果一个页面锁定了应用程序对象,而第二个页面尝试执行相同操作,而第一个页面仍处于锁定状态,则第二个页面将等待第一个页面完成,或者直到Server.ScriptTimeout
达到限制。
一个例子:
<%@ Language="VBScript" %>
<%
Application.Lock
Application("PageCalls") = Application("PageCalls") + 1
Application("LastCall") = Now()
Application.Unlock
%>
This page has been called <%= Application("PageCalls") %> times.
在上面的示例中,该Lock
方法一次阻止多个客户端访问变量 PageCalls。如果应用程序没有被锁定,两个客户端可以同时尝试增加变量 PageCalls。
如果您使用解锁的应用程序对象会有后果。例如,如果您想实现一个全局计数器:-
Application("myCounter") = Application("myCounter") + 1
上面的代码有时会算错。此代码读取、添加和分配。如果两个线程尝试同时执行此操作,它们可能会读取相同的值,然后写入相同的值,将 myCounter 递增 1 而不是 2。
需要的是确保第二个线程在第二个线程写入之前无法读取 myCounter。因此这是更好的: -
Application.Lock
Application("myCounter") = Application("myCounter") + 1
Application.Unlock
当然,如果锁被持有很长时间,特别是如果应用程序有其他用途不受持有锁的代码影响,那么就会出现并发问题。
因此,您应该避免需要长时间锁定应用程序的设计。
如果一个页面试图锁定已经锁定的 Application 对象,它将一直等到持有锁定的页面释放它。这通常会很快(ASP 代码通常应该只持有足够长的时间来访问存储在应用程序中的共享对象)。