背景:最近在做多线程方面的工作,工作中发现多线程中很多坑,这里就有一个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. node-wechat 微信推送消息

    https://github.com/nswbmw/node-wechat/blob/master/index.js

  2. ARM汇编指令集5

    为什么需要多寄存器访问指令? ldr/str每周期只能访问4字节内存,如果需要批量读取.写入内存时太慢,解决方案是stm/ld 举例(uboot start.S 537行)   stmia  sp, ...

  3. Struts05---动态查询

    01.在上面案例的login.jsp页面新增 <%-- 2.动态方法的调用 前提是在 struts.xml文件中开启 不推荐! --%> <a href="user/use ...

  4. Activity传递参数——传递简单数据

    一.新建一个空的工程 二.在主界面中添加一个按钮 三.新建一个空的activity,并命名为TheAty 四.修改MainActivity.java中的onCreate函数 protected voi ...

  5. Android自定义控件之仿美团下拉刷新

    美团的下拉刷新分为三个状态: 第一个状态为下拉刷新状态(pull to refresh),在这个状态下是一个绿色的椭圆随着下拉的距离动态改变其大小. 第二个部分为放开刷新状态(release to r ...

  6. 简单使用JDOM解析XML

    原文:http://liuwentao.iteye.com/blog/59978 使用JDOM解析XML一.前言JDOM是Breet Mclaughlin和Jason Hunter两大Java高手的创 ...

  7. mcake活动维护常见问题记录【wap端】 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

    ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ wap端问题及解决方法 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ 一.wap端弹窗 .Dialogbg-Select{ background-co ...

  8. WEB-INFO里面的jsp文件不能通过href 访问,而只能通过 servlet访问

    href="<%=basePath %>index.jsp"> 这种确实 可以在jsp页面跳转至另一个页面,只不过要放在WEB-INFO外面,也就是项目根目录下面 ...

  9. Leetcode 807. Max Increase to Keep City Skyline

    class Solution(object): def maxIncreaseKeepingSkyline(self, grid): """ :type grid: Li ...

  10. Linux 下spark安装

    一.安装前提: 1.java环境(jdk1.8) 2.scala环境(2.0) 3.python 环境(3.5)  :注如果使用pyspark的话,这个才是必须的. 二.spark安装 在官网下载安装 ...