有一个链表 里面存放了很多对象。
  每个对象都有多个方法 但有一个相同的方法(比如close方法) 也就是调用该方法以后该对象就无效了 就从链表里头删除了
  我现在是对整个列表做了一个互斥 这个互斥从 查找链表之前开始 到 查找完链表元素 并调用元素的方法以后结束
  这样没有什么问题。。但是明显效率不好 
  
  我想从查找链表元素开始 到查找链表结束做个互斥 调用元素方法就不在互斥代码里头了
  但是这样只有一种情况会出问题
  
  比如我查找完毕以后 调用某个方法 比如read 此时另一个线程也查找链表但是调用close方法。。此时程序运行就出错了
因为read正在执行 但是close已经把对象析构掉了。。
下面给个例子代码
 没有问题但是效率底的
 map<int,Object *> map; lock();
 object *po = map.find(1);
 if (po != NULL)
{
  po->read();
 //po->close(); 进行该操作会调用map.easer操作 删除对象。
}
 unlock();map<int,Object *> map;
 lock();
 object *po = map.find(1);
unlock();
po ->read();
//po->close(); 如果一个线程查找调用read没有结束时,另一个线程查找调用close程序就会崩了。。

解决方案 »

  1.   

    我想达到的要求是lock只保护那个链表结构 而 对象的函数调用从别的地方保护但是不知道具体怎么搞。。
      

  2.   

    就是不全部lock时 当调用对象的read时 另外一个线程的close阻塞住 等待read执行完 在执行
      

  3.   

    你实际上是把链表保护跟对象保护混为一谈了。链表保护是用来保护链表结构的,例如一个线程在遍历链表的时候,假若另一个线程在插入元素,则第一个链表的遍历就可能出错,因此,对链表的操作必须互斥。当取出链表中所保存的某个对象之后,对象的操作就跟链表无关了(不可能改变链表结构),因此对链表结构的锁定可以解除。但如果两个线程都取出了同一个对象进行操作,那么该对象就可能发生混乱。你所想到的还只是Close跟其他操作之间的相互影响,可你想到没有,假若两个线程同时进行Read,难道就没问题了?所以这里也必须加锁。不过,如果两个线程分别对位于链表不同位置的对象进行操作,这两者显然不该互斥(例如po1->read跟po2->close之间没有任何关系),所以,必须每个对象分别拥有一个独立的互斥锁——也就是说:应该在这些对象的结构中包含一个用来锁定的成员变量。此时,对哪个对象进行操作,就把哪个对象锁住。
      

  4.   

    楼上的 read之间不用互斥我之间给整个链表加锁也是没办法 才那样做的 你说的给成员变量加锁也是不行的。。因为close操作会销毁对象 而成员变量也就销毁了。。我现在是在链表里头 给对象的操作方法加上计数 这样如果read的查找操作先进去 就给某个变量+1 close操作直到该变量为0才执行 
      

  5.   

    按照你所描述的问题分析,你不仅仅要给链表上锁,你还需要给结构Object内部上一个互斥的锁,用来保证对象内部的数据同步。
      

  6.   

    难道你的对象除了close之外,就没有任何其它操作会改变对象的内容了?如果有的话,那么当一个线程在进行改变对象内容的操作的时候,另一个使用该对象的线程几乎必然会遇到数据不一致而导致错误的情况。要想解决这个问题,就必须在每个操作的时候,都对该对象进行单独锁定。
    我说的不是让你给成员变量加锁,而是在对象体内包含一个CEvent、CMutex、CCriticalSection之类的成员变量,然后在所有操作中,都先对该变量lock,操作完成后再unlock。
      

  7.   

    楼上的不行的  你那样做 容易出现 read 等待 close结束的情况。close已经把 对象给销毁了。。锁也被销毁了 read执行就会出错所以 我用的引用计数。。在查找列表的互斥里头 增加引用计数  然后执行close之前等待计数为0没出什么问题了
      

  8.   

    如果你的close没有放在查找列表的互斥里头的话,仍然会出问题。
      

  9.   

    你可以把满足 “需要调用close函数”这个条件的节点 “删除并带出”,
    这个操作加上互斥。由于 删除结点,就是修改了你要保护的东西,所以要加锁。然后,单独调用 被带出的对象的close函数
    (你也可以把多个 删除的结点都放到另一个新链表里,再用一个函数,统一删除)