读书人

关于线程同步的有关问题求解

发布时间: 2013-10-19 20:58:23 作者: rapoo

关于线程同步的问题,求解
有个小程序如下:


public class shareMemory
{
public int Memory { get; set; }
}
public class increaseMemory
{
private shareMemory test;
public increaseMemory(shareMemory obj)
{
this.test = obj;
}
public void increase()
{
for (int i = 0; i < 100000; i++)
{
test.Memory++;
}
}
}
class Program
{
static void Main(string[] args)
{
shareMemory obj = new shareMemory();
Task[] tasks = new Task[5];
for (int i = 0; i < 5; i++)
{
tasks[i] = new Task(new increaseMemory(obj).increase);
tasks[i].Start();
}
for (int i = 0; i < 5; i++)
{
tasks[i].Wait();
}
Console.WriteLine(obj.Memory);
Console.ReadKey();
}
}

问题是如果我不将共享对象设置为线程安全对象,那么程序计算结果就不会是正确结果,但是这五个线程即便会出现打断彼此的情况,也应该会记录自己的运行情况。在获得CPU的使用权的时候也还是能够按照原来的断点继续运行。也就是说即便打断也能够自加100000次。求解答,各位大神 线程
[解决办法]
这是最基本的常识问题
test.Memory++;
不是原子操作。
它相当于这样一些操作:
int x = test.Memory; line 1
x = x + 1; line 2
test.Memory = x; line 3
我们假设Memory目前等于1。
A线程开始执行前两条,执行到2,此时x=2
A线程被打断,B线程开始执行前两条,B线程的局部变量(不是前面的那个x)x=2
此时B线程挂起,执行A线程第三行,test.Memory=2
B线程此时的x是脏数据,还是2,它用这个数据去更新,结果test.Memory还是2。

可见我们做了2个相加的操作,结果其实只加了一次。
更糟糕的是,如果A线程做了10次,B线程切入,那么它还是用2去覆盖,等于A线程的9次相加全白费了。

读书人网 >C#

热点推荐