zoukankan      html  css  js  c++  java
  • Parallel线程安全问题

    废话不多说,上代码:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    namespace ParallelTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<Product> products = new List<Product>();
                 Parallel.For(0, 1000000, (i) =>
                {
                    Product product = new Product();
                    product.Name = "name" + i;
                    product.Category = "Category" + i;
                    product.SellPrice = i;
                    products.Add(product);
                });
                
                Console.WriteLine(products.Count);
                Console.ReadLine();
            }
        }
    
        class Product
        {
            public string Name { get; set; }
    
            public string Category { get; set; }
    
            public int SellPrice { get; set; }
        }
    }
    

    猜一下,运行结果是多少,是999999?抱歉不是的,结果!= 999999。

    运行结果

    Net 4.0引入了System.Threading.Tasks,简化了我们进行异步编程的方式,而不用直接与线程和线程池打交道,但这也引入了线程安全问题。

    System.Threading.Tasks中的类型被称为任务并行库(TPL)。TPL使用CLR线程池(说明使用TPL创建的线程都是后台线程)自动将应用程序的工作动态分配到可用的CPU中。

    其中Parallel是指数据并行,其提供的Parallel.For()或Parallel.ForEach()方法,可以以并行方式对数组或集合中的数据进行迭代。

    那之所以出现这个结果,很显然了,是多线程操作集合导致的线程安全问题。

    总之,多线程操作集合时一定要注意线程安全的问题,不管是通过Thread、ThreadPool、Task、Parallel还是PLINQ。

    解决方案很简单:

    1. 加锁
    2. 使用并行集合(System.Collections.ConCurrent)

    对于这个问题,我知道其存在潜在的线程安全问题,但是不确定其导致的结果如何?当我截图到处询问无果时,才想到自己动手写demo去验证问题。这也是我写这篇文章的初衷:提醒自己,遇到问题,不要凭空猜测,要有动手验证的决心。

  • 相关阅读:
    关于asp.net中Repeater控件的一些应用
    Linux查看程序端口占用情况
    php 验证身份证有效性,根据国家标准GB 11643-1999 15位和18位通用
    给Nginx配置一个自签名的SSL证书
    让你提升命令行效率的 Bash 快捷键 [完整版]
    关系数据库常用SQL语句语法大全
    php 跨域 form提交 2种方法
    Vimium~让您的Chrome起飞
    vim tab设置为4个空格
    CENTOS 搭建SVN服务器(附自动部署到远程WEB)
  • 原文地址:https://www.cnblogs.com/sheng-jie/p/8612586.html
Copyright © 2011-2022 走看看