当前位置: 移动技术网 > IT编程>开发语言>.net > 关于Paralle.For的求和问题

关于Paralle.For的求和问题

2018年12月07日  | 移动技术网IT编程  | 我要评论

干干净净的傅雷,苹果se价格,河北枣强中学

.net4中加入了并行机制——所谓并行就是同时开辟若干个线程来进行计算。这些线程由于都是互相独立的,所以在进行一些分布式(比如各自不同的工作)的时候是非常简单,不过要把这些处理结果汇总起来却不是那么容易——下面来看一个非常简单的例子(求1~1000的和)。
如果你尝试使用以下的代码计算,恐怕令你大跌眼镜!
[c#]
int sum = 0;
parallel.for(0, 1000,i => {sum+=i;});
[vb.net]
dim sum as integer = 0
parallel.[for](0, 1000, function(i)
sum += i)
究其原因就是.net会默认开辟一些线程同时进行“sum+=i”的计算。那么由于sum被这些线程同时使用,往往是一个线程还没有处理完毕,另外一个线程又介入了,自然无法得到正确结果了。
解决这个问题的办法有许多:
【一】分解法:
所谓分解法,就是针对“同一个变量”被不同线程“共享”这一诟病而提出的。——也就是说,把1~1000求和分成若干块进行处理(等于给每一个线程分配了不同的内存)。最后把分布计算的结果进行累计汇总即可。结果如下:
[c#]
int[] numbers = enumerable.range(1, 1000).toarray();
int[] values=new int[4];
int sum = 0;
parallel.for(0, 4, i => { values[i] = new program().gettotal(i * 250, 250, numbers); });
sum = values.sum();
console.writeline(sum);
[vb.net]
 
dim numbers as integer() = enumerable.range(1, 1000).toarray()
dim values as integer() = new integer(3) {}
dim sum as integer = 0
parallel.[for](0, 4, function(i)
values(i) = new program().gettotal(i * 250, 250, numbers))
sum = values.sum()
console.writeline(sum)
 
【二】使用静态变量
静态变量本身就具备“同步”的能力(这种例子在简单工厂中也可以窥见)。所以这里显然可以使用,代码如下:
[c#]
 
public class program
        {
            static int sum = 0;
            static void main(string[] args)
            {
                parallel.for(1, 1001, i => {sum+=i;});
                console.writeline(sum);
            }
        }
 
[vb.net]
 
public class program
    shared sum as integer = 0
    private shared sub main(args as string())
        parallel.[for](1, 1001, sub(i)
        sum += i)
        console.writeline(sum)
    end sub
end class
 
【三】使用volatile变量(一般编译器为了优化性能,往往把常用的变量复制一份到寄存器中,然后直接对寄存器进行操作,等到操作完毕之后再写回原来的内存中。多线程会导致寄存器中的变量不同步,所以结果也不对。而volatile就是告诉编译器直接从内存中读取那个数字进行操作,而不是拷贝到寄存器之后处理):
[c#]
 
public class program
        {
            volatile int sum = 0;
            public void showresult()
            {
                parallel.for(1, 1001, i => { sum+=i; });
                console.writeline(sum);
            }

            static void main(string[] args)
            {
                program p = new program();
                p.showresult();
            }
        }
 
[vb.net,由于vb.net没有此特性,所以使用thread.volitaleread每次读取最新的数值后进行累加]
 
public class program
    dim sum as integer = 0
    public sub showresult()
        parallel.for(1, 1001, sub(i)
                                  thread.volatileread(sum)  '总是读取最新数值
                                  sum = sum + i
                                  thread.sleep(2)
                              end sub)
        console.writeline(sum)
    end sub

    public shared sub main(args as string())
        dim p as new program()
        p.showresult()
    end sub
end class
 
【四】使用lock(锁住一个变量,然后直到该线程操作完毕自动释放变量,另外一个线程进来操作……如此反复而已):
[c#]
 
 public class program
        {
            int sum = 0;
            public void showresult()
            {
                object obj = new object();
                parallel.for(1, 1001, i => { lock (obj) { sum += i; thread.sleep(10); } });
                console.writeline(sum);
            }

            static void main(string[] args)
            {
                program p = new program();
                p.showresult();
            }
        }
 
[vb.net]
 
public class program
    private sum as integer = 0
    private obj as new object
    public sub showresult()
        dim obj as new object()
        parallel.for(1, 1001, sub(i)
                                  synclock obj
                                      sum = sum + i
                                  end synclock
                              end sub)
                                  console.writeline(sum)
    end sub
end class

module m
    sub main()
        dim p as new program
        p.showresult()
    end sub
end module
 
【五】使用internlock函数:
[c#]
 
 public class program
        {
            int sum = 0;
            public void showresult()
            {
                parallel.for(1, 1001, i => { interlocked.add(ref sum, i); });
                console.writeline(sum);
            }

            static void main(string[] args)
            {
                program p = new program();
                p.showresult();
            }
        }
 
[vb.net]
 
public class program
    private sum as integer = 0
    public sub showresult()
        parallel.[for](1, 1001, sub(i)
                                    interlocked.add(sum, i)
                                end sub)
        console.writeline(sum)
    end sub

    shared sub main(args as string())
        dim p as new program()
        p.showresult()
    end sub
end class

 

 

摘自 serviceboy

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网