您在寻找这样的东西吗?
public MyController : Controller
{
private static object Lock = new object();
public ActionResult MyAction()
{
lock (Lock)
{
// do your costly action here
}
}
}
如果线程当前正在处理该操作中的代码,则上述内容将阻止任何其他线程执行该操作lock
block.
更新:这是它的工作原理
方法代码始终由线程执行。在负载较重的服务器上,有可能有 2 个或更多不同的线程进入并开始并行执行一个方法。根据问题,这就是你想要防止的。
请注意如何private Lock
对象是static
。这意味着它在控制器的所有实例之间共享。因此,即使堆上构造了该控制器的 2 个实例,它们也共享同一个 Lock 对象。 (该对象甚至不必命名为 Lock,您可以将其命名为 Jerry 或 Samantha,它仍然具有相同的用途。)
这是发生的事情。您的处理器一次只能允许 1 个线程输入一段代码。正常情况下,线程A可以开始执行代码块,然后线程B可以开始执行它。因此理论上你可以让 2 个线程同时执行相同的方法(或任何代码块)。
The lock
可以使用关键字来防止这种情况。当线程进入包裹在 a 中的代码块时lock
部分,它“拾取”锁定对象(后面括号中的内容)lock
关键字,又名Lock
, Jerry
, or Samantha
,应将其标记为static
场地)。在执行锁定部分的持续时间内,它“保留”锁定对象。当线程退出锁定部分时,它“放弃”锁定对象。从线程获取锁对象开始,直到它放弃锁对象,所有其他线程都被阻止进入代码的锁定部分。实际上,它们会“暂停”,直到当前正在执行的线程放弃锁对象。
因此线程 A 在 MyAction 方法的开头获取锁对象。在放弃锁对象之前,线程B也尝试执行该方法。但是,它无法获取锁对象,因为它已经被线程 A 持有。因此它等待线程 A 放弃锁对象。当它完成时,线程 B 就会获取锁对象并开始执行代码块。当线程 B 完成执行该块时,它会为下一个委托处理此方法的线程放弃锁对象。
...但我不确定这是否是您正在寻找的...
使用这种方法并不一定会使您的代码运行得更快。它只保证一段代码一次只能由1个线程执行。它通常用于并发原因,而不是性能原因。如果您可以在问题中提供有关您的具体问题的更多信息,可能会有比这个更好的答案。
请记住,我上面提供的代码将导致其他线程在执行该块之前等待。如果这不是您想要的,并且您希望“跳过”整个操作(如果它已经由另一个线程执行),那么请使用更像 Oshry 的答案。您可以将此信息存储在缓存、会话或任何其他数据存储机制中。