思路:我们让后台Thread.Sleep一段时间,来模拟一个耗时操作,而这个时间可以由前台提供。
我们开启两个或以上的页面,第一个耗时5秒(提交5000),第二个耗时1秒(提交1000)。
期望的测试结果:
不加Lock锁,第二个页面会先执行完,因为耗时短(1秒)。
加了Lock锁,第二个页面会一直等待,直到第一个页面执行完成后再进行。
后台:
public class DBController : Controller
{
/// <summary>
/// 显示页面
/// </summary>
/// <returns></returns>
[HttpGet]
public IActionResult Concurrency()
{
return View();
}
/// <summary>
/// 模拟耗时操作
/// </summary>
/// <returns></returns>
[HttpPost]
public IActionResult ConcurrencySubmit(string msec)
{
if (!string.IsNullOrEmpty(msec))
{
System.Threading.Thread.Sleep(int.Parse(msec));
LogHelper.Info("submit:" + msec);
}
return View("Concurrency");
}
}
前台页面 Concurrency.cshtml:
@using(Html.BeginForm("ConcurrencySubmit", "DB", FormMethod.Post))
{
@Html.TextBox("msec",1000)
<button>提交</button>
}
然后开两个页面,第一个5秒,第二个1秒,同时提交。
发现第二个页面先执行完毕了,因为耗时最短。
接下来我们使用Lock来进行防并发处理,修改后台代码:
public class DBController : Controller
{
private static object locker = new object();
/// <summary>
/// 显示页面
/// </summary>
/// <returns></returns>
[HttpGet]
public IActionResult Concurrency()
{
return View();
}
/// <summary>
/// 模拟耗时操作
/// </summary>
/// <returns></returns>
[HttpPost]
public IActionResult ConcurrencySubmit(string msec)
{
lock (locker)
{
if (!string.IsNullOrEmpty(msec))
{
System.Threading.Thread.Sleep(int.Parse(msec));
LogHelper.Info("submit:" + msec);
}
}
return View("Concurrency");
}
}
同样的方法,再次提交。这次会发现第二个页面会等待,直到第一个页面执行完成后才执行