fah*_*hmi 12 c# asp.net multithreading
在以下示例中,单击"提交"按钮时,静态变量Count的值将递增.但这个操作线程安全吗?是否正在使用Appliation对象进行此类操作?这些问题也适用于Web表单应用程序.
单击"提交"按钮时,计数似乎总是增加.
查看(剃刀):
@{
Layout = null;
}
<html>
<body>
<form>
<p>@ViewBag.BeforeCount</p>
<input type="submit" value="Submit" />
</form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.BeforeCount = StaticVariableTester.Count;
StaticVariableTester.Count += 50;
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
静态类:
public class StaticVariableTester
{
public static int Count;
}
Run Code Online (Sandbox Code Playgroud)
dca*_*tro 13
不,这不对.+ =运算符分3步完成:读取变量的值,将其增加1,分配新值.扩展:
var count = StaticVariableTester.Count;
count = count + 50;
StaticVariableTester.Count = count;
Run Code Online (Sandbox Code Playgroud)
线程可以在任何两个步骤之间被抢占.这意味着如果Count为0,并且两个线程+= 50同时执行,则可能Count是50而不是100.
T1读Count为0.T2读Count为0T1 增加0 + 50T2 增加0 + 50T1 分配50到 CountT2 分配50到 CountCount 等于50此外,它也可能在您的前两个指令之间被抢占.这意味着两个并发线程可能都设置ViewBag.BeforeCount为0,只有再增加StaticVariableTester.Count.
使用锁
private readonly object _countLock = new object();
public ActionResult Index()
{
lock(_countLock)
{
ViewBag.BeforeCount = StaticVariableTester.Count;
StaticVariableTester.Count += 50;
}
return View();
}
Run Code Online (Sandbox Code Playgroud)
或者使用 Interlocked.Add
public static class StaticVariableTester
{
private static int _count;
public static int Count
{
get { return _count; }
}
public static int IncrementCount(int value)
{
//increments and returns the old value of _count
return Interlocked.Add(ref _count, value) - value;
}
}
public ActionResult Index()
{
ViewBag.BeforeCount = StaticVariableTester.IncrementCount(50);
return View();
}
Run Code Online (Sandbox Code Playgroud)
增量不是原子的,因此不是线程安全的.
添加两个32位整数,并将第一个整数替换为sum,作为原子操作.
你会这样使用它:
Interlocked.Add(ref StaticVariableTester.Count, 50);
Run Code Online (Sandbox Code Playgroud)
就个人而言,我会把它包装在你的StaticVariableTester课堂上:
public class StaticVariableTester
{
private static int count;
public static void Add(int i)
{
Interlocked.Add(ref count, i);
}
public static int Count
{
get { return count; }
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想要返回的值(根据dcastro的评论),你可以随时做:
public static int AddAndGetNew(int i)
{
return Interlocked.Add(ref count, i);
}
public static int AddAndGetOld(int i)
{
return Interlocked.Add(ref count, i) - i;
}
Run Code Online (Sandbox Code Playgroud)
在您的代码中,您可以做到
ViewBag.BeforeCount = StaticVariableTester.AddAndGetOld(50);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1063 次 |
| 最近记录: |