zoukankan      html  css  js  c++  java
  • 并行化时要注意的线程安全与任务安全

    在串行编程时,操作都是按顺序执行的,比如数字从1到100000递增,就必然的是1、2、3、4……100000。代码如下

    for (int i = 1; i <= 100000; i++)
                {
                    Console.WriteLine(i);   
                }



    然而,在并行化编程时,因为是并行运行的,所以执行顺序会与系统和硬件有关,这样一来,执行顺序就变的不可预知,比如。

    Parallel.For(1,100001,(i)=>Console.WriteLine(i));


    很明显,最大的数100000在前面就已经输出了,如果执行多次,会看到这个结果不是固定的。

    因为执行顺序的不确定性,所以当我们在多个线程或者多个任务中去同时操作一个变量时,就可能引发问题。比如

      int testValue = 0;
                Task.Factory.StartNew(() =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        testValue++;
                        Console.WriteLine("Add:" + testValue);
                    }
    
                });
                Task.Factory.StartNew(() =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        testValue--;
                        Console.WriteLine("subtract:" + testValue);
                    }
                });
                Console.ReadLine();


    在两个task中执行增加和减少操作,结果变的不可测。而如果我们在线程或者任务中去依赖于这样的变量作判断条件时,后果就会变的相当严重。这里,testValue变量是一种非线程安全/非任务安全的,如果要对其实现递增和递减就得采用原子操作,即Interlocked.Increment和Interlocked.Decrement。

    既然有非线程安全/非任务安全,自然就有对应的线程安全/任务安全,这包含在System.Collections.Concurrent的命名空间中。ConcurrentQueue、ConcurrentStack、ConcurrentBag、ConcurrentDictionary,这些对应了Queue、Stack、Array/List、Dictionary。

    比如我们需要在A线程添加对象,又需要在B线程中移除对象时,可能道先想到的是List,但List在多线程操作会出问题,因为并行运行会导致并发,结果有可能在同一时间内对List进行操作。这时就要考虑使用线程安全/任务安全的类型来替代。

    总的来说,在多线程或者多任务的并行化操作时,要优先考虑线程安全/任务安全的数据类型,如果一定要用非线程安全的数据时,就得增加同步控制(比如原子操作Interlocked、锁lock、信号量SemaphoreSlim/Semaphore、倒计事件CountdownEvent、共享事件ManualResetEventSlim/ManualResetEvent、自旋锁SpinLock等)。


  • 相关阅读:
    开源项目之Android StandOut(浮动窗口)
    小智慧7
    安卓学习
    asp.net学习Request和Response的其他属性
    bash中的转义
    POJ 1833 排列
    Django点滴(四)ORM对象存取
    POJ 1681 Painter's Problem
    linux2.6.32在mini2440开发板上移植(21)之WebServer服务器移植
    [gkk传智]static与多态及向下向上转型,及多态调用总结
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7605071.html
Copyright © 2011-2022 走看看