我有一个主线程,还有一个操作类
然后操作类里有个list和一个对象
然后在主线程里修改这个对象和集合
这样锁会有问题嘛?
麻烦各位大神看下了,谢谢using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            List<A> list_1 = new List<A>();
            list_1.Add(new A { Id = 1, Name = "AAA" });
            list_1.Add(new A { Id = 2, Name = "BBB" });
            list_1.Add(new A { Id = 3, Name = "CCC" });            List<A> list_2 = new List<A>();
            list_2.Add(new A { Id = 5, Name = "11" });
            list_2.Add(new A { Id = 6, Name = "22" });
            list_2.Add(new A { Id = 7, Name = "33" });            List<Work> list_work = new List<Work>();
            Work work_B = new Work(new A { Id = 90, Name = "YYYY" }, list_2);
            list_work.Add(work_B);
            Console.ReadLine();
            Console.WriteLine(DateTime.Now.ToShortTimeString());
            Console.WriteLine("等待锁资源!");
            work_B.a.Id = 88;
            work_B.a.Name = "wuchizhitu";
            work_B.list_a.Add(new A { Id = 4, Name = "DDD" });
            Console.WriteLine("赋值结束!");
            Console.WriteLine(DateTime.Now.ToShortTimeString());
            Work work_A = new Work(new A { Id = 22, Name = "XXXX" }, list_1);
            list_work.Add(work_A);
            Console.WriteLine("Change work_A's Id and Name");
            Console.ReadLine();
            Console.WriteLine(DateTime.Now.ToShortTimeString());
            Console.WriteLine("等待锁资源!");
            work_A.list_a = new List<A> { new A { Id = 10, Name = "CHANGE" }, new A { Id = 30, Name = "XCXCX" } };
            work_A.a = new A { Id = 11, Name = "3333" };
            Console.WriteLine("赋值结束!");
            Console.WriteLine(DateTime.Now.ToShortTimeString());            Console.Read();
        }        public class A
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        public class Work
        {
            private object obj = new object();
            public A a { get; set; }            private List<A> _list_a;
            public List<A> list_a
            {
                get
                {
                    lock (obj)
                    {
                        Console.WriteLine("锁住了list_a GET");
                        return _list_a;
                    }
                }
                set
                {
                    lock (obj)
                    {
                        Console.WriteLine("锁住了list_a SET");
                        _list_a = value;
                    }
                }
            }
            Thread thread;            public Work(A _a, List<A> _list_a)
            {
                a = _a;
                list_a = _list_a;                thread = new Thread(Do);
                thread.IsBackground = true;
                thread.Start();
            }
            private void Do()
            {
                while (true)
                {
                    Task[] task = new Task[3];
                    try
                    {
                        lock (obj)
                        {
                            Console.WriteLine("进入了锁");
                            foreach (var item in list_a)
                            {
                                task[0] = Task.Factory.StartNew(new Action(() => { Thread.Sleep(2000); Console.WriteLine("Task 0 is End"); }));
                                task[1] = Task.Factory.StartNew(new Action(() => { Thread.Sleep(8000); Console.WriteLine("Task 1 is End"); }));
                                task[2] = Task.Factory.StartNew(new Action(() => { Thread.Sleep(2000); Console.WriteLine("Task 2 is End"); }));
                                Task.WaitAll(task);
                            }
                        }
                        Console.WriteLine("出了锁 foreach");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }    }
}

解决方案 »

  1.   

    你只有一个线程,不需要锁
    你 lock (obj) 住的是私有对象,跟没锁一样
      

  2.   

    没呀,还有个主线程会去修改这个集合属性,比如添加 删除对象啥的 ,这时候  那个循环线程还在foreach里循环,这个时候就会报错  集合对象已更改,所以必须锁,但这样锁又感觉有问题
      

  3.   

    你违规了
    在foreach 里改变(增删)作为数据来源的集合,是不允许的!自然就会报错 :集合对象已更改
    锁也没有用
      

  4.   

    多个线程操作集合应该锁住集合,并且使用autoresetevent 来控制线程的等待与继续。在遍历完毕的情况下通知写入数据线程继续即可。
      

  5.   

    粗看楼上的回复。感觉这段代码满满的问题啊
    楼主,先从基础出发。
    1  了解 什么是 lock,
    2  了解foreach不可更改数据源的知识
    3  lock(obj)   中 声明为 
    private static readonly object obj = new object();
    和 private  readonly object writeFile = new object();的区别
    其他问题就不赘述了。
      

  6.   

    写了就忘了来看了,其实你的是对的,只是我那时候实际操作是循环的对象里还有集合也是要循环,感觉用autoresetevent有点混乱,还是直接用lock锁起来,不让主线程去修改集合简单。只是容易引起等待而已。