2011-03-07 51 views
0

这不是一个问题,因为我已经实现了自己的集合,但仍然对此有点好奇。std :: map和线程安全的奇怪问题

我有一个单例提供对各种公共组件的访问,它拥有带有线程ID的这些组件的实例,因此每个线程都应该(并且我检查过)拥有它自己的组件实例,如Oracle数据库访问库。

当运行系统(这是一个C#应用程序被称为C++库)与多个传入的请求似乎一切都运行良好了一阵子,但随后崩溃了与AccessViolation例外。单步执行调试器时,问题似乎出现在一个线程完成并清除其会话信息(保存在std :: map对象中)时,保存在另一个线程的单独集合实例中的会话信息也会被清除。

这是其他人遇到或知道的东西吗?我尝试过四处看看,但找不到任何有关此类问题的信息。

Cheers

+0

“我有一个单身......”那就是那个问题。 :) – GManNickG 2011-03-07 20:27:25

+0

老实说,我很惊讶,没有人说,越早:) – 2011-03-08 08:01:18

回答

2

标准C++容器并不关心线程安全问题。您的代码听起来像是从两个不同的线程修改地图实例,或者修改一个线程中的地图并在另一个线程中读取地图。这显然是错误的。使用一些锁定原语来同步线程之间的访问。

+0

这就是我最初的想法,但检查调试器中的信息,我可以看到,这两个地图都在单独的内存位置。所以当我有:(线程1 - >映射a)和(线程2 - >映射b)当线程1清除“映射a”时,我最终也清除了“映射b”? – 2011-03-07 11:06:38

+0

@ daz-fuller:如果它们实际上是分开的'map',那么你可能有更深的问题。回到调试器,直到你理解了这个问题,或者你可能只是隐藏了bug而不是修复它。 – 2011-03-07 11:24:23

+0

@ daz-fuller:你用什么编译器来编译C++代码?什么版本? – wilx 2011-03-07 11:29:48

0

你如何管理给每个线程自己的会话信息?在那里的某个地方,你有管理这些对象的生命周期的类,这就是它出现错误的地方。

+0

有一个单例处理这些项目,当它被要求时,比如说,它会检查一个调试记录器,看看是否存在该线程,如果没有,则创建一个。这一点工作正常,问题是创建线程特定的实例。一种特定的类型具有清除方法。因此,“线程A”具有“对象A”和“映射A”并且“线程B”具有“对象B”和“映射B”,出于某种原因每次偶尔调用“对象A”的清除方法影响“地图A”和“地图B” – 2011-03-07 12:52:10

+0

因此它会检查某种表格。当线程结束时,它会从某种表中删除它。该表因此被多个线程使用。也要注意迭代器可能失效。 – CashCow 2011-03-07 13:21:07

+0

如果这是静态查找表的问题,那么我期望清除错误的映射,但不是两者。另外我希望一些错误的对象属性被修改,但它们不是,正确的对象是否被修改? – 2011-03-07 13:50:37

1

如果您只想为每个线程分别创建一个对象,那么您可能需要查看boost::thread_specific_ptr

+0

我经常这样做,不幸的是,由于项目的性质,我们仅限于STL和我们自己编写的任何东西:( – 2011-03-07 12:52:48

+0

我建议您查看thread_specific_ptr的代码并自行编写它。 – ronag 2011-03-07 14:16:19