none
假定数组(Array)创建后元素从不更新,多线程通过数组索引访问读取特定元素是否线程安全? RRS feed

  • 问题

  • 如题,我在class里声明一个数组

    public static MyCustomType[] myArray=new MyCustomType[5];

    然后在class 实例方法里面(多线程)用索引访问元素 myArray[i], i 是一个Local 变量,通过Array.BinarySearch 静态方法返回,这样不会有线程安全性问题吧?


    • 已编辑 GuYuming 2017年11月29日 10:30
    2017年11月29日 10:29

全部回复

  • 我以为多线程操作数据的要点,如何将数据集(List,Array,Collection)合理分配(切分)到多个线程中运算,运算完成后再合并结果等操作  。

    一个数据集让多个线程同时读写,结果不可预计。如果是同一个线程读写,则不会有冲突。


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2017年11月30日 1:04
  • “一个数据集让多个线程同时读写,结果不可预计”,

    官方文档明确表示 Array 下面的 public static 方法都是 thread safe 的,只是其他方法不保证,我要问的就是用索引访问具体元素是否线程安全。如果不是线程安全,用BinarySearch 返回一个数组索引有啥意义呢?BinarySearch本身是 public static 方法,按官方文档的意思,应该是线程安全的。



    Update: 我的问题集中在一个 c# Array 让多个线程同时读,不涉及写

    • 已编辑 GuYuming 2017年11月30日 9:13
    2017年11月30日 1:13
  • 同时读取不存在线程安全性问题,因为这里显然没有先后冲突问题”, 我是担心 myArray[i] 在底层执行的时候会否有线程间共享的存储?我的理解数值下标最终会映射到内存地址,这个映射过程会不会产生先后冲突?

    更进一步(不仅局限于myArray[i]),C#的代码转成IL,机器代码后,除了在C#里声明的本地变量,会否产生一些临时的存储,这部分存储会否产生线程冲突? 我印象中 .net 的虚拟机和Java 差不多,都是堆栈虚拟机,我的理解中间存储都会压栈,这个栈是不是都是线程间隔离的呢?我读到过C#方法里声明的本地变量是在栈上分配的空间,这里的栈和虚拟机层次上提到的栈是不是一回事?


    • 已编辑 GuYuming 2017年11月30日 3:28
    2017年11月30日 1:20
  • Hi,

    >>,C#的代码转成IL,机器代码后,除了在C#里声明的本地变量,会否产生一些临时的存储,这部分存储会否产生线程冲突?

    据我对GC的理解,应该不会有冲突。 

    这些临时变量的存储空间,肯定是GC分配的,和管理的? GC的在分配空间的时候,会首先去检查一下,当前有没有足够的空间来容纳现在的大小,如果没有足够的空间,就会执行GC回收不用的内存,然后会把这些碎片内存,给重新整理。

    当然在执行gc的时候,其他线程都会被短暂的挂起。 不会被其他线程访问。

    Best Regards,

    Hart 


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年12月5日 9:34
    版主
  • ldelem.ref

    • Load the element at index onto the top of the stack as an O. The type of the O is the same as the element type of the array pushed on the CIL stack.

    摘自 http://mattwarren.org/2017/05/08/Arrays-and-the-CLR-a-Very-Special-Relationship/ 

    看上去通过索引访问一个引用类型的数组元素的操作会有专门的 CIL 指令

    A conforming CLI shall guarantee that read and write access to properly aligned memory locations no larger than the native word size (the size of type native int) is atomic (see §I.12.6.2) when all the write accesses to a location are the same size.  Atomic writes shall alter no bits other than those written.  Unless explicit layout control (see Partition II (Controlling Instance Layout)) is used to alter the default behavior, data elements no larger than the natural word size (the size of a native int) shall be properly aligned.  Object references shall be treated as though they are stored in the native word size.

    from http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf 

    • 已编辑 GuYuming 2017年12月7日 9:30
    2017年12月7日 8:59
  • http://www.cnblogs.com/dwlsxj/p/MSIL.html  提到了Call Stack 和 Evaluation Stack, 都是按线程分的;

    根据 https://stackoverflow.com/questions/19476595/does-each-managed-thread-have-its-own-corresponding-native-thread 的回答,几乎可以认为 Managed Thread 和 Native Thread 就是一一对应的

    2017年12月7日 9:54
  • Hi,

    Yes, a .NET Thread maps to a native operating system thread on all current CLR hosts.

    从他的回答来看,的确是managed thread 和 native thread 是对应关系的。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年12月11日 7:57
    版主
  • 我都是加锁再读取,从没有直接操作的时候。

    而且你的array存放的数据应该是array让你在的类私有的,不应该把array公开。

    2017年12月13日 8:43