C#数组是否线程安全?
尤其是
- 创build一个函数来获取一个数组和一个索引作为参数。
- 创build一个元素数组。
- 创build一个计数循环。
- 在新线程的循环内部,使用传入的索引器将对象的新实例分配给数组。
我知道如何pipe理线程等。我有兴趣知道这是否是线程安全的做某事。
class Program { // bogus object class SomeObject { private int value1; private int value2; public SomeObject(int value1, int value2) { this.value1 = value1; this.value2 = value2; } } static void Main(string[] args) { var s = new SomeObject[10]; var threads = Environment.ProcessorCount - 1; var stp = new SmartThreadPool(1000, threads, threads); for (var i = 0; i < 10; i++) { stp.QueueWorkItem(CreateElement, s, i); } } static void CreateElement(SomeObject[] s, int index) { s[index] = new SomeObject(index, 2); } }
我相信,如果每个线程只在数组的一个单独的部分工作,一切都会好起来的。 如果要共享数据(即在线程之间进行通信),则需要某种内存屏障来避免内存模型问题。
我相信 ,如果你产生了一堆线程,每个线程都填充它自己的数组部分,然后等待所有这些线程完成使用Thread.Join
,这将做足够的障碍,让你安全。 我目前没有任何支持文件,请注意…
编辑:您的示例代码是安全的。 在任何时候,两个线程访问相同的元素 – 就好像它们每个都有单独的variables。 但是,这并不总是有用的。 在某些情况下,线程通常会希望共享状态 – 一个线程将要读取另一个线程所写的内容。 否则,他们写入共享数组,而不是自己的私有variables是没有意义的。 这就是你需要小心的地方 – 线程之间的协调。
数组上的MSDN文档说:
此types的公共静态(在Visual Basic中为Shared)成员是线程安全的。 任何实例成员不保证是线程安全的。
此实现不为数组提供同步(线程安全)包装器; 但是,基于Array的.NET Framework类使用SyncRoot属性提供它们自己的集合的同步版本。
枚举枚举本质上不是一个线程安全的过程。 即使集合同步,其他线程仍然可以修改集合,这会导致枚举器抛出exception。 为了确保枚举过程中的线程安全性,可以在整个枚举过程中locking集合,或者捕获其他线程所做更改所导致的exception。
所以不,他们不是线程安全的。
通常,当一个集合被认为是“不是线程安全的”,这意味着并发访问可能会在内部失败(例如,读取List <T>的第一个元素是不安全的,而另一个线程在列表的末尾添加一个元素:List <T>可能会调整底层数组的大小,并且在将数据复制到数组之前,读访问可能会转到新数组)。
这样的错误对于数组是不可能的,因为数组是固定大小的并且没有这种“结构变化”。 有三个元素的数组比三个variables没有更多或更less的线程安全性。
C#规范对此没有任何说明; 但是很清楚,如果你知道IL并阅读CLI规范 – 你可以得到一个托pipe的引用(比如那些用于C#“ref”参数的引用)给数组中的一个元素,然后执行正常和不稳定的加载并存储到它。 CLI规范描述了这种加载和存储的线程安全保证(例如<= 32位元素的primefaces性)
所以,如果我正确地解决你的问题,你想要使用不同的线程填充一个数组,但将只分配给每个数组元素? 如果是这样,这是完全线程安全的。
您提供的示例与Microsoft自己的C#4.0并行扩展的工作方式非常相似。
这for循环:
for (int i = 0; i < 100; i++) { a[i] = a[i]*a[i]; }
变
Parallel.For(0, 100, delegate(int i) { a[i] = a[i]*a[i]; });
所以,是的,你的榜样应该是确定的。 这里有一篇关于C#中新的并行支持的博文 。