下面的代码运行了好久都没出问题
static void Main(string[] args) { var stop=new Stopwatch(); var ths=new List<Thread>(); long times = 0, maxTimes = 5000000; var ulist=new List<int>(); ulist.AddRange(Enumerable.Range(1, 1000)); #if M //ImmutableList<int> list=ImmutableList<int>.Empty; //var builder=list.ToBuilder(); //builder.AddRange(Enumerable.Range(1,1000)); //list = builder.ToImmutable(); stop.Start(); for (int i = 0; i < 50; i++) { var i1 = i; var th=new Thread(() => { while (true) { if (Interlocked.Read(ref times) >= maxTimes) { stop.Stop(); //list = builder.ToImmutable(); Console.WriteLine("times:" + stop.ElapsedMilliseconds / 1000.0 + " length:" + ulist.Count); return; } //builder.Add(i1); //builder.Remove(i1); var dic=new Dictionary<int,int>(); int prev = 0; foreach (var i2 in ulist) { if (i2 - prev != 1) { throw new Exception("unsaft"); } dic.Add(i2, 0); prev = i2; } dic.Clear(); dic = null; Interlocked.Increment(ref times); //Console.WriteLine(Interlocked.Read(ref times)); } }); th.Start(); ths.Add(th); } #endif Console.Read(); }
"代码运行了好久都没出问题" 然后呢?
var dic=new Dictionary<int,int>(); int prev = 0; foreach (var i2 in ulist) { if (i2 - prev != 1) { throw new Exception("unsaft"); } dic.Add(i2, 0); prev = i2; } dic.Clear();
Dictionary没有重复的key,i2 - prev一直等于1,我就想知道List<T> foreach这个操作是不是线程安全??????
如果foreach操作过程中List<T>
不会被修改,是线程安全的
只要不改变集合中的元素,无论是foreach内部还是外部,都是线程安全的。但如果有改变集合中元素,则必须加锁或线程同步才行。
百度 线程安全的Dictionary
我知道问题不是这个
@张小军: 知识点有3个.
1.线程安全问题指的是多写或又读又写的情况.多读的情况下并不会有.
2.foreach每次都会get一个新的迭代器.并且是只读的.
3.你得写操作是局部变量.自然也没有问题.
所以猜测你应该是不明白什么叫线程安全.所以让你去看下线程安全的dictionary理解下.
@吴瑞祥: 好,谢谢教导,我目前的情况下,我只需要要多线程环境读,写入操作已经在应用程序启动时候已完成了,读的时候用了 foreach和 list[i],那我读的时候是否应该加锁???
@吴瑞祥: 里面我用了Dictionary<int,int>,这个我只是测试foreach过程中会不会产生重复的key,如果产生重复的key,那么就意味着foreach有问题
@张小军: foreach的迭代器是每次都获取一个新的. 所以不会有问题
再起一个线程,改变ulist的count,就有可能会有问题