代码如下,Lock为什么锁不到list变量呀!using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;namespace ConsoleApplication1
{
    class Program
    {
        
        static void Main(string[] args)
        {
            ReadMessage rm = new ReadMessage();
            rm.startW();
            Thread.Sleep(100);
            GetMessage gm = new GetMessage();
            gm.startC();            Console.ReadKey();
        }            
        
    }
    public class ReadMessage
    {
        GetMessage gm = new GetMessage();
        public void startW()
        {
            System.Threading.Thread th = new System.Threading.Thread(new ThreadStart(startWW));
            th.Start();
        }
        private void startWW()
        {
            List<string> list = new List<string> { };
            while (true)
            {
                list = gm.retruelist();
                if (list != null)
                {
                    foreach (string str in list)
                        Console.WriteLine(str + "  Read");
                }
            }        }
    }
    public class GetMessage
    {
        
        public void startC()
        {
            Thread th = new Thread(new ThreadStart(startCC));
            th.Start();
        }
        private void startCC()
        {
            int i = 0;
            while (true)
            {
                stratsomething(i.ToString());
                Console.WriteLine(i+"  Write");
                if (i++ >= 100)
                    break;
            }        }
        public void stratsomething(string _str)
        {
            ListMessage.Set(_str);
        }
        public List<string> retruelist()
        {
            return (List<string>)ListMessage.Get();
        }    }    public static class ListMessage
    {
        public static List<string> listmessage = new List<string> { };        private static object _Root = new object();        public static object Get()
        {
            object result = null;
            lock (_Root)
            {
                result = listmessage;
                Thread.Sleep(300);
                listmessage.Clear();
            }
            return result;
        }        public static void Set(string value)
        {
            lock (_Root)
            {
                listmessage.Add(value);
            }
        }
    }
}

解决方案 »

  1.   

    就是说 我想实现
    这个list写的时候不允许读,
    当这个list被读出后 
    在输出的完清空list的时间段,不允许写
      

  2.   

    你运行一下就知道了,在读list的时候,它还是给写进了数据
      

  3.   

    哦对了
       Console.ReadKey();
    这句注释掉才能看到结果
      

  4.   

    那你应该 if (list != null)
     {
         foreach (string str in list)
             Console.WriteLine(str + "  Read");
      }在这里加lock
      

  5.   

    在我这运行结果是,一段读,一段写,最后总抛出容器被修改异常(Unhandled Exception: System.InvalidOperationException: Collection was modified;enumeration operation may not execute.)其实你的程序本质上就是两个线程在不停地并发调用ListMessage类的Get和Set函数,这两个函数同时操作一个静态字段listmessage,而关键是你的Set函数没有一次性将所有数据写完,因此比如当Set(1)函数完成后,lock结束,而下一个进来的线程不一定就是Set(2),可能是Get,于是程序会一会读一会写,而且当Get函数返回后,一个线程用foreach循环,另一个线程可能会此时进入Set函数操作同一个容器,则抛出异常
      

  6.   

    那该如何实现呢这个list写的时候不允许读,
    当这个list被读出后  
    在输出的完清空list的时间段,不允许写
      

  7.   

    第一种方法就是是最直接的,就是将所有插入操作全部放到Set函数中,不过这种方法打破了程序的原有逻辑。第二种方法就是在startW和startC中进行线程同步操作,如下修正后的代码class Program
        {
            static void Main(string[] args)
            {
                ReadMessage rm = new ReadMessage();
                rm.startW();
                Thread.Sleep(100);
                GetMessage gm = new GetMessage();
                gm.startC();            Console.ReadKey();
            }
        }
        public class ReadMessage
        {
            GetMessage gm = new GetMessage();
            public void startW()
            {
                System.Threading.Thread th = new System.Threading.Thread(new ThreadStart(startWW));
                th.Start();
            }
            private void startWW()
            {
                List<string> list = new List<string> { };
                while (true)
                {
                    bool entered = Monitor.TryEnter(typeof(GetMessage), 1000);
                    try
                    {
                        list = gm.retruelist();
                        if (list.Count != 0)
                        {
                            foreach (string str in list)
                                Console.WriteLine(str + "  Read");
                            break;
                        }                    Thread.Sleep(1000);
                    }
                    finally
                    {
                        if (entered)
                            Monitor.Exit(typeof(GetMessage));
                    }
                }        }
        }
        public class GetMessage
        {
            public void startC()
            {
                Thread th = new Thread(new ThreadStart(startCC));
                th.Start();
            }
            private void startCC()
            {
                int i = 0;
                while (true)
                {
                    bool entered = Monitor.TryEnter(typeof(GetMessage), 1000);
                    try
                    {
                        stratsomething(i.ToString());
                        Console.WriteLine(i + "  Write");
                        if (i++ >= 100)
                            break;
                    }
                    finally
                    {
                        if (entered)
                            Monitor.Exit(typeof(GetMessage));
                    }
                }        }
            public void stratsomething(string _str)
            {
                ListMessage.Set(_str);
            }
            public List<string> retruelist()
            {
                return (List<string>)ListMessage.Get();
            }    }    public static class ListMessage
        {
            public static List<string> listmessage = new List<string> { };        private static object _Root = new object();        public static object Get()
            {
                lock (_Root)
                {
                    Thread.Sleep(300);
                    return listmessage;
                }
            }        public static void Set(string value)
            {
                lock (_Root)
                {
                    listmessage.Add(value);
                }
            }
        }