2011-04-10 139 views
1

防止两个不同的人同时执行相同方法的最佳方法是什么?例如,用户A与用户B在同一页面上。两者都在完全同时执行该事件的代码的同时按下页面上的按钮。我试图让其他人等待完成。ASP.NET竞争条件

有没有一种常见的方法来做到这一点?

这里有更多的一些信息..

这是一个简单的游戏,你买的网站成员(如FB上的既有游戏)。查询字符串是用户的ID。我遇到了两个人同时点击购买的问题。一个获得用户,另一个则亏钱。所以我试图在同一时间阻止购买,以防止发生。

+0

你可以在一个静态变量上使用'lock',但是这听起来像你会在你的应用程序中创建一个争用点。如果是2,那么页面上有100个用户呢? – CriGoT 2011-04-10 11:31:12

+4

我们可以知道方法和它在做什么吗?通常,对服务(RESTful,理想情况下)提出的每个请求都是独立处理的原子单元。它通常不依赖于其他请求,特别是其他用户上下文中的请求。很可能有更好的方法来设计这个。 – David 2011-04-10 11:32:19

回答

4

A Page将为每个请求创建实例,因此假设您拥有的逻辑位于实例成员中,并且不访问任何共享的内容,则不需要进行锁定。

如果碰到共享资源,有几种方法可以强制锁定。一种方法是使用lock陈述,例如

private static someObject = new Object(); 

public void SomeMethod() 
{ 
    lock(someObject) 
    { 
     // do something with your shared resource. 
    } 

} 

一般来说,你的目标应该是避免使用锁尽可能地(虽然也有在需要锁定许多情况下)。

编辑:

如果你持有支持事务例如数据源数据就像数据库一样,那么您首先需要检查用户尝试购买的内容在用户点击页面上的“是”与收到响应的应用程序之间的时间内尚未购买。因此,您需要检查数据源以确定它是否已被购买,如果尚未购买,则为该用户“购买”该商品。这应该在交易中完成,以便它是原子的,因此如果“购买”该项目的行为成功,您只需从用户的账户中取钱。

3

您可以与[MethodImpl]属性装饰它:

[MethodImpl(MethodImplOptions.Synchronized)] 
public static void SomeMethod() 
{ 
    ... 
} 

这样,只有一个线程可以执行的方法和其他人将等待。这相当于把lock放到整个方法体中。

+0

注意如果使用此方法创建死锁。 – 2011-04-10 11:39:27

+0

根据Jeffrey Richter和他的书“CLR via C#”3rd ed。,建议不要使用此属性。该属性使用'this'变量的Monitor锁,这是不推荐的。相反,建议创建一个专用实例字段进行锁定。如果它是一个静态方法,则该属性使用Monitor类来锁定对类​​型的类型对象的引用,这也是不被推荐的,并且可能导致微妙的错误和问题。 – 2012-02-08 00:32:56