首页 新闻 会员 周边 捐助

多线程环境下,对List<T>进行foreach操作是线程安全的吗??

0
悬赏园豆:5 [待解决问题]

下面的代码运行了好久都没出问题

 

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();
        }
张小军的主页 张小军 | 初学一级 | 园豆:182
提问于:2016-11-13 18:26
< >
分享
所有回答(5)
0

"代码运行了好久都没出问题" 然后呢?

 

~扎克伯格 | 园豆:1923 (小虾三级) | 2016-11-13 18:27
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这个操作是不是线程安全??????

支持(0) 反对(0) 张小军 | 园豆:182 (初学一级) | 2016-11-13 18:30
0

如果foreach操作过程中List<T>不会被修改,是线程安全的

dudu | 园豆:30778 (高人七级) | 2016-11-13 20:43
0

只要不改变集合中的元素,无论是foreach内部还是外部,都是线程安全的。但如果有改变集合中元素,则必须加锁或线程同步才行。

xuanbg | 园豆:266 (菜鸟二级) | 2016-11-13 20:53
0

百度 线程安全的Dictionary

吴瑞祥 | 园豆:29449 (高人七级) | 2016-11-13 23:08

我知道问题不是这个

支持(0) 反对(0) 张小军 | 园豆:182 (初学一级) | 2016-11-13 23:33

@张小军: 知识点有3个.

1.线程安全问题指的是多写或又读又写的情况.多读的情况下并不会有.

2.foreach每次都会get一个新的迭代器.并且是只读的.

3.你得写操作是局部变量.自然也没有问题.

所以猜测你应该是不明白什么叫线程安全.所以让你去看下线程安全的dictionary理解下.

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2016-11-14 10:28

@吴瑞祥: 好,谢谢教导,我目前的情况下,我只需要要多线程环境读,写入操作已经在应用程序启动时候已完成了,读的时候用了 foreach和 list[i],那我读的时候是否应该加锁???

支持(0) 反对(0) 张小军 | 园豆:182 (初学一级) | 2016-11-14 10:35

@吴瑞祥: 里面我用了Dictionary<int,int>,这个我只是测试foreach过程中会不会产生重复的key,如果产生重复的key,那么就意味着foreach有问题

支持(0) 反对(0) 张小军 | 园豆:182 (初学一级) | 2016-11-14 10:41

@张小军: foreach的迭代器是每次都获取一个新的. 所以不会有问题

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2016-11-14 10:46
0

再起一个线程,改变ulist的count,就有可能会有问题

hahanonym | 园豆:1460 (小虾三级) | 2016-11-14 08:50
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册