• 如何正确使用并行计算对集合进行写操作?


    using System;
    using System.Collections.Generic;
    using System.Collections.Concurrent;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Diagnostics;

    namespace ParallelTest1
    {
    public class CalcTask
    {
    public event EventHandler<TaskItemEventArgs> OnTaskFinish;

    public void ExecuteTasks()
    {
    int icount = 100;
    List
    <Task> items = new List<Task>(icount);
    PInitializeTask(items, icount);
    Console.WriteLine(items.Count);

    List
    <Task> items2 = new List<Task>();
    SInitializeTask(items2, icount);

    Console.WriteLine(items2.Count);

    Console.ReadKey();
    }

    private void PInitializeTask(List<Task> items,int iCount)
    {
    Stopwatch stopwatch
    = new Stopwatch();
    stopwatch.Start();

    Parallel.For(
    0, iCount, new ParallelOptions()
    {

    }, i
    =>
    {
    lock (items) //如果不加锁,观察最终集合的个数?
    {
    items.Add(
    new Task()
    {
    Source
    = i,
    Dest
    = i + i,
    });

    //if (items.Count == iCount)
    OnTaskFinish(this, new TaskItemEventArgs()
    {
    ThreadId
    =Thread.CurrentThread.ManagedThreadId,
    Data
    =items,
    });
    }
    });

    stopwatch.Stop();
    Console.WriteLine(
    "Parallel loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds);

    }

    private void SInitializeTask(List<Task> items, int iCount)
    {
    Stopwatch stopwatch
    = new Stopwatch();
    stopwatch.Start();
    for(int i=0;i<iCount;i++)
    {
    items.Add(
    new Task()
    {
    Source
    = i,
    Dest
    = i + i,
    });

    OnTaskFinish(
    this, new TaskItemEventArgs()
    {
    ThreadId
    = Thread.CurrentThread.ManagedThreadId,
    Data
    = items,
    });
    }
    stopwatch.Stop();
    Console.WriteLine(
    "Sequential loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
    }
    }

    public class Task
    {
    public int Source { get; set; }
    public int Dest { get; set; }

    public override string ToString()
    {
    return string.Format("{0}-{1}", this.Source, this.Dest);
    }
    }

    public class TaskItemEventArgs:EventArgs
    {
    public int ThreadId{get;set;}
    public object Data{get;set;}
    }
    }
     
    static void Main(string[] args)
    {
    Console.WriteLine(
    "Processor Count:" + Environment.ProcessorCount);
    CalcTask task1
    = new CalcTask();
    task1.OnTaskFinish
    += new EventHandler<TaskItemEventArgs>((sender, e) =>
    {
    Console.WriteLine(
    string.Format("Finish:{0}-{1}", e.ThreadId, (e.Data as List<Task>).Count));
    });
    task1.ExecuteTasks();


    }
    在上述代码中,我测试的结果规律如下:
    如果并行中,不加lock,如果是向集合填充100万个对象 ,那么并行代码 执行完毕后,那个集合的数目永远都是小于100万,我的结果显示是80多万。。。。估计中间发生冲突导致部分的项添加不成功,但是.net并没有报错,这样很容易让我们中招。所以用一般集合时需要小心,这里也证实了一般的集合List<T>并不是线程安全的。。。
    后来我换成System.Collections.Concurrent.ConcurrentDictionary<int, Task>试了下,发现不用加lock,结果也是正确的,所以大家在并行运算中记得多使用这个哈希结构。。。但是线程安全的。
  • 相关阅读:
    背下来就是电脑高手(转)
    split+ Pattern切割字符串
    java中方法中声明三个点“...”作用
    MRUnit测试
    configuration默认设置
    chmod|chown|chgrp和用法和区别
    hadoop 一些文件操作
    关闭SVN服务
    Hadoop如何计算map数和reduce数
    链式mapreduce
  • 原文地址:https://www.cnblogs.com/yulinlover/p/2004515.html
Copyright © 2020-2023  润新知