C++ 是否有一个联锁系统?C++;

C++ 是否有一个联锁系统?C++;,c++,multithreading,concurrency,thread-safety,interlocked,C++,Multithreading,Concurrency,Thread Safety,Interlocked,请注意-这些构建是针对VS2008/VS2010构建的,我不能使用任何11个构建 想象一下,我的订阅者正在收听某个出版商的节目。我的发布者有一个订阅者指针容器。在我的voiddetach(issubscriber*)中,我不会锁定订阅者列表,而是将该订阅者的指针“NULL”掉,因为没有更好的单词 //My container in the publisher. Inserts to not invalidate, removals only invalidate iterators point

请注意-这些构建是针对VS2008/VS2010构建的,我不能使用任何11个构建

想象一下,我的订阅者正在收听某个出版商的节目。我的发布者有一个订阅者指针容器。在我的voiddetach(issubscriber*)中,我不会锁定订阅者列表,而是将该订阅者的指针“NULL”掉,因为没有更好的单词

//My container in the publisher.  Inserts to not invalidate, removals only invalidate iterators pointing to the removed element, for this reason we NULL
Container<ISubscriber *> myContainer;

Now in the publisher...
void NotifySubscribers(){
   foreach(subscriber in container){
      if(subscriber)//This is my problem
         subscriber->notify()
   }
}
在这里,参考计数器被自动递减并针对零进行测试,然后并且只有在等于零时,数据才会被释放

我有没有办法根据指针的有效性调用函数

编辑1:我需要根据评论澄清一下,谢谢你的回复。发布者不对订阅服务器的“内存释放”负责,因此不会发生泄漏。在通知之后,发布者将通过一个循环来清除容器,方法是删除空的订阅服务器

至于订户本身。当他们脱离时,他们只是脱离了对发布者的倾听。他们自己将生活在静态对象中(这是我们需要的契约)。为什么?因为我们不能在通知期间持有锁。唯一的其他选择是使用Share_Ptr,由于将来的版本控制,决定不将其合并到此DLL中

我创建了一个手写的共享\u ptr,但是我突然想到,对一个没有包装在资源管理类中的对象的任何引用都会落入同一个陷阱,只会推动“要求”,即订阅者必须确保在其所述订阅者的实现中不引用任何悬而未决的引用

//My container in the publisher.  Inserts to not invalidate, removals only invalidate iterators pointing to the removed element, for this reason we NULL
Container<ISubscriber *> myContainer;

Now in the publisher...
void NotifySubscribers(){
   foreach(subscriber in container){
      if(subscriber)//This is my problem
         subscriber->notify()
   }
}
这让我们回到刚才所说的,订阅者不能被“释放”,目前所有使用它的客户端都是静态对象。我们只是展望未来。一些用户是遗留应用程序,不容易从该应用程序等引入启用的共享应用程序

有没有一种方法可以让我使用某种互锁的东西,比如测试和调用是原子的

对于考试,是的,会有办法的。您只需要比较一个指针

做这个电话,我怀疑。您需要一名警卫在呼叫周围,即关键区域

有没有一种方法可以让我使用某种互锁的东西,比如测试和调用是原子的

对于考试,是的,会有办法的。您只需要比较一个指针


做这个电话,我怀疑。您需要在呼叫周围设置一个防护装置,即关键部分。

您可以使用“智能指针”策略来延迟指针的置零。只要有人对指针有引用(由联锁引用计数确定),就保持指针有效;当计数变为零时,可以安全地设置为空。

您可以使用“智能指针”策略来延迟设置指针的空值。只要有人对指针有引用(由联锁引用计数确定),就保持指针有效;当计数变为零时,可以安全地设置为空。

如果可以在遍历容器时删除订阅服务器,则需要比简单的原子测试更高级别的同步/生命周期管理。类似于引用计数器(例如,可能包装在共享指针中)。请注意,在执行
notify()
时,您还需要防止对象被删除。但是,您会泄漏您的IsSubscriber对象吗?您确实需要一个原子来执行此操作(而不是使用
mutex
)?众所周知,无锁结构很难正确使用,特别是对于更复杂的结构,因此通常不值得付出努力。在这种情况下,原子测试和调用(如果存在)对您没有帮助,因为您不能保证
订阅服务器
在线程位于
notify
中时不会被删除。如果在容器中行走时可以删除订阅服务器,然后,您需要比简单的原子测试更高级别的同步/生命周期管理。类似于引用计数器(例如,可能包装在共享指针中)。请注意,在执行
notify()
时,您还需要防止对象被删除。但是,您会泄漏您的IsSubscriber对象吗?您确实需要一个原子来执行此操作(而不是使用
mutex
)?众所周知,无锁结构很难正确使用,特别是对于更复杂的结构,因此通常不值得付出努力。在这种情况下,原子测试和调用(如果存在的话)对您没有帮助,因为您不能保证
订户
在线程位于
通知
中时不会被删除。我们试图避免一个关键部分,这是问题背后的动机。这很可能是不可能的。谢谢,我们都在一定程度上尽量避免它们。但事情不可能总是原子化的。使用带有旋转计数的临界段进行一些分析。关键部分锁定时会“耗费时间”,如果它可以自由通过,并且在你的应用程序中大部分时间都会发生这种情况,那么成本可能比你想象的要低。我听到了。我们绝对不能在调用notify时保持锁定,我可能必须锁定、复制资源、解锁、调用notify、清理。再次尝试避免这种情况,但这可能是不可能的。旋转计数,是否有一个时间的经验法则,是否有一个你发现自己在使用的神奇数字?谢谢默认值通常是4000左右(无论如何在Windows上)。不过,我在英特尔代码示例中看到过类似的用法:spinCount=NumThreads*1000;如果(spinCount>8000)spinCount=8000;我们正试图避免一个关键部分,这是问题背后的动机。这很可能是不可能的。谢谢,我们都在一定程度上尽量避免它们。但事情不可能总是原子化的。使用