【问题标题】:Constructing a C++ object (the MFC CRecordset) thread-safely线程安全地构造 C++ 对象(MFC CRecordset)
【发布时间】:2009-10-06 14:48:13
【问题描述】:

我们正在尝试构建一个提供 MFC CRecordset(或者,实际上是 CODBCRecordset 类)线程安全的类。对于各种功能,例如打开和移动记录集(我们将这些调用与关键部分括起来),实际上一切似乎都很好,但是,仍然存在一个问题,这个问题似乎在实践中引入了死锁。

问题似乎出在我们的构造函数上,像这样:

CThreadSafeRecordset::CThreadSafeRecordset(void) : CODBCRecordset(g_db)
{ // <-- Deadlock!
}

尽管我们保护了封闭的 Close 调用,但另一个线程可能最终在 CThreadSafeRecordset::Close() 中结束,但这并不重要,因为构造函数不知道线程。我认为最初的 CRecordset 类是罪魁祸首,在施工时做坏事。我一直在寻找解决这个问题的编程技术,但我不确定什么是最好的解决方案?由于我们没有代码,也无法控制构造函数中的其他代码,所以我们不能在临界区中包装任何特殊的东西......?

更新:感谢您的意见;我已经将我最终得到的内容标记为我的问题的答案。这与返回 shared_ptr 作为返回实例相结合,以便于更新现有的线程不感知代码。

【问题讨论】:

    标签: c++ multithreading mfc thread-safety recordset


    【解决方案1】:

    您可以将CThreadSafeRecordset 构造函数设为私有,然后提供一个参与锁定并返回实例的公共工厂方法。

    【讨论】:

      【解决方案2】:

      如果无法使 CODBCRecordset 将其线程不安全操作移出构造函数(例如,默认构造函数后跟 Initialize() 调用),则始终可以使用组合而不是继承。让 CThreadSafeRecordset 成为 CODBCRecordset 的包装器,而不是它的子类。这样一来,您就可以随时明确地构建您的记录集,并且可以以任何适当的严谨性来保护它。

      当然,缺点是您必须包装每个您希望公开的 CODBCRecordset 方法,即使是那些与您的线程保证无关的方法。 cpp 文件中的 C 宏(这样它就不会逃脱并影响您的客户端)可能会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-05
        • 1970-01-01
        • 2010-09-05
        相关资源
        最近更新 更多