背景:最近在做多线程方面的工作,工作中发现多线程中很多坑,这里就有一个List添加对象的误区,这里做个分享跟大家讲讲这个坑是怎么形成的怎么样避免。

示例:

代码及错误:

如果单单只从程序逻辑上看,应该没有逻辑错误,但是结果却是是有为空值的情况,这时候有些多线程经验的读者可能会想到,构造函数也是一个函数,有可能在往List中添加对象的时候,构造函数还没有将对象返回就执行了添加操作,造成了这个问题的出现,下面我们来验证一下这个观点是否正确。

从图中可以看到,在对象new之后立即执行了取属性操作,如果构造函数没有返回立即执行后面肯定会出现空指针异常,但是这里并没有出问题,说明不是构造函数返回结果的问题,同时也说明了构造函数是具有线程安全的。

为此可以怀疑这个问题是优于List.Add方法造成的,为此,查看一下List.Add方法的源码可以了解其中的原委。

点开this.EnsureCapacity(this.size+1);方法,如下图所示:

这时候,我们就可以猜测到问题就出现在这个容量扩展方法这里了,于是我尝试着修改List的最初容量,使之不需要进行容量扩展,此时程序运行正常,说明问题的确就在这里。

虽然说问题解决了,问题的原因也知道了,但是为什么会有这样的问题呢?内存扩容是如何形成这个错误的呢,于是和六爷讨论了一下这个问题,很感谢六爷指点迷津,让我知道了这其中的具体原因,我画个简图给大家讲解一下,希望大家能看明白:

验证:

假设真的是这个原因造成的应该出现空值的位置应该都是2的整数次幂之后的值,并且如果内存越大拷贝的时间越长,出现空值的几率就越大,于是改造程序,可以验证六爷的这个猜测:

代码:

结果,8192=4096*2,16384=8192*2:

解决方案:

1.扩容List的初始容量为集合需要的实际容量或更大

2.给List.Add方法加锁

3.使用List的线程安全版本,如下图所示:

源代码:

https://download.csdn.net/download/hirisw/10769789

C#多线程List的非线程安全性的更多相关文章

  1. Java 多线程:什么是线程安全性

    线程安全性 什么是线程安全性 <Java Concurrency In Practice>一书的作者 Brian Goetz 是这样描述"线程安全"的:"当多 ...

  2. Linux c readdir是非线程安全,需用readdir_r,要注意用静态变量当做返回值的函数的非线程安全性

    readdir函数: struct dirent *readdir(DIR *dirp); The  data  returned by readdir() may be overwritten by ...

  3. JAVA中的线程安全与非线程安全

    原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...

  4. Java 非线程安全的HashMap如何在多线程中使用

    Java 非线程安全的HashMap如何在多线程中使用 HashMap 是非线程安全的.在多线程条件下,容易导致死循环,具体表现为CPU使用率100%.因此多线程环境下保证 HashMap 的线程安全 ...

  5. Java多线程编程(3)--线程安全性

    一.线程安全性   一般而言,如果一个类在单线程环境下能够运作正常,并且在多线程环境下,在其使用方不必为其做任何改变的情况下也能运作正常,那么我们就称其是线程安全的.反之,如果一个类在单线程环境下运作 ...

  6. Java多线程之非线程安全

    在Java多线程中我会重点总结五个如下的技术点: 1.非线程安全是如何出现的 2.synchronized对象监视器为Objec时的使用 3.synchronized对象监视器为Class时的使用 4 ...

  7. 【多线程补充】SimpleDateFormat非线程安全与线程中、线程组中异常的处理

    1.SimpleDateFormat非线程安全的问题 类SimpleDateFormat主要负责日期的转换与格式化,但在多线程环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateF ...

  8. java 多线程 线程安全及非线程安全的集合对象

    一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读取完之后,其他线程才可以使用.防止出现数据不一致或 ...

  9. 刨根问底系列(3)——关于socket api的原子操作性和线程安全性的探究和实验测试(多线程同时send,write)

    多个线程对同一socket同时进行send操作的结果 1. 概览 1.1 起因 自己写的项目里,为了保证连接不中断,我起一个线程专门发送心跳包保持连接,那这个线程在send发送数据时,可能会与主线程中 ...

随机推荐

  1. appium自动化测试(一)

    一. appium的引入 二. adb adb(Android Debug Brige)是用来连接安卓手机和PC端的调试桥梁,通过adb服务,在PC端命令行界面对手机或者模拟器进行全面的操作 安装: ...

  2. ASP.NET Core 简单引入教程

    0.简介 开源.跨平台 1.环境安装 参考官方教程   Core 官方文档 2.向世界问个好 sheel/cmd 下: dotnet --help // 查看帮助 dotnet new *     / ...

  3. Visual Studio 2008常见问题

    1.asp.net在什么软件上运行?学习asp往往需要测试asp程序,电脑不能直接测试,需要装IIS才能运行,但装IIS要么需要安装盘,要么需要安装包,而且设置也很复搜索杂.这里给大学推荐两个替代II ...

  4. js最基础的作用域问题

    1.什么是作用域? 每个变量和函数,都有其作用的范围,超出这个范围,就不能使用了,这个范围就叫做“作用域”,我们举个例子,一个文件中的变,在另一个文件中直接访问,是访问不到的,两个文件是两个“域”,两 ...

  5. Mysql中文汉字转拼音的实现(每个汉字转换全拼)

    -- 创建汉字拼音对照临时表 CREATE TABLE IF NOT EXISTS `t_base_pinyin` ( `pin_yin_` varchar(255) CHARACTER SET gb ...

  6. R语言:数据的分割-计算-整合(split-apply-aggregate)

    当获取到原始数据时,我们通常的做法是对该数据进行分割成小片段,然后对各小片段进行计算统计,最后整合成最终的数据.这是统计学里数据处理的一般规律. R语言为我们提供了相应的函数来分别处理这三个阶段任务. ...

  7. 《Drools7.0.0.Final规则引擎教程》第4章 4.2 auto-focus

    auto-focus 在agenda-group章节,我们知道想要让AgendaGroup下的规则被执行,需要在代码中显式的设置group获得焦点.而此属性可配合agenda-group使用,代替代码 ...

  8. php curl请求。header头中添加请求信息

    function get_data($key,$authorization,$url){ $headers = array(    'api-key:'.$key,    'authorization ...

  9. Android开源框架-Annotation框架(以ViewMapping注解为例)

    Annotation 分类 1 标准 Annotation 包括Override, Deprecated, SuppressWarnings,标准 Annotation 是指 Java 自带的几个 A ...

  10. LeetCode Next Greater Element III

    原题链接在这里:https://leetcode.com/problems/next-greater-element-iii/description/ 题目: Given a positive 32- ...