虽然线程可以在一定程度上提高程序运行的效率,但也会产生一些副作用。让 我们先看看如下的代码:
class Increment { private int n = 0; private int max; public Increment(int max) { this.max = max; } public int result { get { return n; } set { n = value; } } public void Inc() { for (int i = 0; i < max; i++) { n++; } } } class Program { public static void Main() { Increment inc = new Increment(10000); Thread[] threads = new Thread[30]; for (int i = 0; i < threads.Length; i++) { threads[i] = new Thread(inc.Inc); threads[i].Start(); } for (int i = 0; i < threads.Length; i++) { threads[i].Join(); // 等待30个线程都执行完 } Console.WriteLine(inc.result); //输出n的值 } }
上面的程序的基本功能是使用Increment的Inc方法为n递 增max,所不同的是,将在Main方法中启动30个线程同时执行Inc方法。在本例中 max的值是10000(通过Increment的构造方法传入)。读者可以运行一下这个程序 ,正常的结果应该是300000,但通常不会得到这个结果,一般获得的结果都比 300000小。其中的原因就是Inc方法中的n++上,虽然从表面上看,n++只是一条简 单的自增语言,但从底层分析,n++的IL代码如下:
ldsfld// 获得n的初 始值,并压到方法栈中
ldc.i4.1// 将1压到方法栈中
add// 从方 法栈中弹出最顶端的两个值,相加,然后将结果保存在方法栈中
stfld// 从当前方法栈中弹出一个值,并更新类字段n
对于上面每一条IL语句是线 程安全的,但是n++这条C#语句需要上面的四步才能完成,因此,n++这条语句并 不是线程安全的。只要在执行stfld指令之前的任何一步由于其他线程获得CPU而 中断,那么就会出现所谓的“脏”数据。
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c#
, int
, 线程
, 方法
, max
Increment
c站、c语言、cf、ch、c罗,以便于您获取更多的相关知识。