一个List<T>的链表,T有字段state,程序会很频繁的请求改变state的值
现在我改怎么处理List<T> 移除某个节点的问题?如果我加锁了,那么频繁请求state的变化,就会阻塞到那里了。
如果不加锁,多线程的情况下,有会出错?

解决方案 »

  1.   

    lock(o)
    {
        //
    }
      

  2.   

    TO jksharp
    请你看清问题好不好?
      

  3.   

    private static Object SyncObj =new Object();lock(SyncObj)
    {
       foreach(T t in List<T>)
       {
           //判断下删除吧
           List<T>.Remove(t);
           //List<T>.RemoveAt(i);
       }
    }这样还不够,在你修改List<T>中的state值的地方也要使用
    lock(SyncObj)
    {
       //修改List<T>中的state
    }但是如果修改的地方多了,是否会遗漏呢?因此,建议你吧List<T>写成管理列表类,所有的添加,删除,修改,判断,获取值等操作都放在类中,并且使用一个统一的同步锁SyncObj就可以了.还有,你担心频繁的锁会影响频繁修改的效率,我可以告诉你lock的效率是极快的,这个在MSDN中有介绍,你不必要担心,只要做好同步就可以了.
      

  4.   

    to much0726你的想法和我的想法差不多,REMOVE时LOCK了,应该不会对修改STATE造成很大的影响。另外我觉得修改STATE的时候可以不锁,最多数据"脏"而已,就算要锁也可以只锁T,而不锁LIST。
      

  5.   

    顺便说下,初学线程的人比较容易写lock(this),lock(string)等错误的代码.这个我之前也错过,在VS的帮助文档中有很明确的提出,使用私有对象作为同步锁是比较安全的,使用全局字符变量和类变量作为同步锁都是极其危险的,this其实是类.不能用来做同步对象.
      

  6.   

    是的,但是添加和删除List时需要锁List,否则会出现枚举对象改变不能继续遍历的错误.
      

  7.   

    TO much0726lock(List<T>) 
    {
    }
    就是LOCK链表对象,这样写可以不?
    或者
    mutex.WaitOne();
    list<T>.Remove(n);
    mutex.ReleaseMutex();
    这样的方式呢?
      

  8.   

    我觉得你在修改state 的时候也应该加锁,脏读对程序逻辑有影响
      

  9.   


    public class xmlContent
        {
            private static XmlDocument _xml = null ;        public static XmlDocument LoadXml(string xmlpath)
            {
                if (_xml != null) { return _xml; }
                lock (_xml)
                {
                    _xml = new XmlDocument();
                    _xml.Load(xmlpath);
                    return _xml;
                }
                
            }        public static bool ModifyXml(object t)
            {
                lock (_xml)
                {
                    //自己处理
                    return true;
                }
            }这是刚才帮别人写的修改xml的,可以参考ModifyXml方法
      

  10.   

    锁T可以吗?你删除的是List中的元素,不是马上将T释放.我觉得还是要锁List
      

  11.   

    lock(List <T>) 


    这样写,如果List<T>是private类型的,理论上倒没什么问题,不过感觉怪怪的.mutex.WaitOne(); 
    list <T>.Remove(n); 
    mutex.ReleaseMutex(); 
    这个和Lock方式的等价的,看个人喜好了,个人推荐使用lock,不为别的就因为它的效率最高(在某本书上看过的,忘记了),信号量的控制有它的另外的优势,一时说不清.如果简单就使用lock
      

  12.   

    我说的锁T是指修改STATE的时候,不是add remove LIST的时候哈。呵呵
      

  13.   

    继承list,private static object lockObject = new Object();
    然后在add和remove方法里
    lock(lockObject)
        {
    add remove操作
    }
      

  14.   

    请大家继续讨论如下情况
    foreach(T t in List<T>)
    {
         t.State = n;
    }另一线程
    Lock(List<T>)
    {
        List<T>.Remove(List<T>.Count-1);
    }会不会出现如下问题,就是foreach进行到最后一次循环了,但还没有对State赋值,这个时候线程2触发了,要将最后个节点移除了。这个时候执行顺序是怎么的,如果是先执行移除,那么赋值就要异常的嘛。小弟不懂啊。
      

  15.   

    lock问题其实也是比较复杂的东西。
      

  16.   

    在多线程下就算你要修改List<T>中state的值也是要锁的,假如那条要修改state的线程在执行到获取List的index或关键字代码准备执行修改List<T>代码时,CPU转到执行另一条线程,这条线程移除了List<T>要修改index之前的某条数据,那么到CPU转回执行修改线程时,就会出现问题了
    我想无论是新增,修改,还是删除最好还是上锁比较好
      

  17.   


    老兄, 你太强大了,小弟顶礼膜拜中...MSDN 的原文:List 泛型类线程安全
    此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。但不能保证任何实例成员是线程安全的。只要不修改该集合,List 就可以同时支持多个阅读器。通过集合枚举在本质上不是一个线程安全的过程。在枚举与一个或多个写访问竞争的罕见情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。