我有一个静态数组变量,由两个线程共享。
我想了解如果我将数组变量分配给Thread1
中的另一个数组对象,而Thread2
迭代数组时会发生什么。
即
在主题1中
MyStaticClass.MyArray = SomeOtherArray
在线程2中:
for (int i = 0; i < MyStaticClass.MyArray.length; i++)
{
//do something with the i'th element
}
答案 0 :(得分:1)
要防止这种情况,您需要使用锁来锁定关键部分。基本上将您的itteration包装在一个锁中将阻止另一个线程在处理它时覆盖该数组
lock关键字确保一个线程不进入代码的关键部分,而另一个线程处于临界区。如果另一个线程试图输入一个锁定的代码,它将等待,阻塞,直到该对象被释放。
答案 1 :(得分:1)
假设MyStaticClass.MyArray
只是一个字段或简单属性。
肯定会发生任何好的或可预测的事情。
我说最有可能的是:
[i]
最后一种情况是由于编译器优化和/或内存模型在.net(以及Java BTW等其他语言)中的工作方式。有一个完整的关键字可以解决此问题(volatile
)http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
答案 2 :(得分:1)
每次迭代都会评估for
循环中的条件。因此,如果另一个线程更改MyStaticClass.MyArray
中的引用,则在下一次迭代中使用此新引用。
例如,此代码:
int[] a = {1,2,3,4,5};
int[] b = {10, 20, 30, 40, 50, 60, 70};
for (int i = 0; i < a.Length; i++)
{
Console.WriteLine(a[i]);
a = b;
}
给出了这个输出:
1
20
30
40
50
60
70
为避免这种情况,您可以使用foreach
:
foreach(int c in a)
{
Console.WriteLine(c);
a = b;
}
给出:
1
2
3
4
5
因为foreach
已翻译,因此它会调用a.GetEnumerator()
一次,然后使用此枚举器(MoveNext()
和Current
)进行所有迭代,而不是访问a
试。
答案 3 :(得分:0)
除了线程2之外,在某些时候开始处理新阵列而不是旧阵列将没有任何后果。当这种情况发生时或多或少是随机的,正如韦斯顿在评论中写道的那样,它甚至可能永远都不会发生。
如果新数组的元素少于旧数组,则可以(但不必)导致运行时异常。