多线程设计,保护C++中的全局成员

Posted

技术标签:

【中文标题】多线程设计,保护C++中的全局成员【英文标题】:Multithreading Design, protect global member in C++ 【发布时间】:2012-10-20 01:09:36 【问题描述】:

我正在使用 QT 编写一个 c++ 应用程序,重点是速度优化。 我想要一些对不同线程具有只读访问权限的全局对象。 在打开线程之前,我必须初始化全局对象并用数据填充它们。

如何保护我的全局对象的集合函数,但仍可以从主函数访问?

现在的示例代码:

myClass.h

class MyObjectClass 
public:
void SetSome(const QList<QString> &value);
QList<QString> GetSome() const;

private:
    QList<QString> m_myMember;
;

main.cpp

#include "global.h" // some like: extern MyObjectClass g_InihalizedInMain;
#include "anyThread.h"

int main()

g_InitializedInMain.SetSome() // This Shut work

MyThread thread;
thread.start();

//..
return 0;

anyThread.cpp:

#include "global.h"

void thread::run()

MyObjectClass newObject = g_InihalizedInMain; //This shut work
g_InitializedInMain.GetSome();                  //This shut work
g_InitializedInMain.SetSome();                  //This shut not work and give me an error during compile time
newObject.SetSome();                    //This shut work

如果您有一些设计想法给我,我会很高兴,非常感谢!

【问题讨论】:

我会尝试使用friend 声明。 【参考方案1】:
class MyPrivateObjectClass : private MyObjectClass

public:
   friend void main();
;

extern MyPrivateObjectClass g_InitializedInMain;

【讨论】:

【参考方案2】:

创建你的全局变量static,这意味着只有一个源文件可以访问它。然后,您可以提供可以从其他线程读取数据的访问器函数。

【讨论】:

【参考方案3】:

对于初学者,我会不惜一切代价避免使用全局变量。

除了全局变量之外,您可以做的是在 main 中实例化一个变量(或者 动态地,或在堆栈上本地,取决于您的偏好) 并将其设置在线程对象中(这称为dependency injection

要仅从 main 控制 MyObjectClass 的设置属性,我可以想到 2 个选项:

    通过 main 中的构造函数设置所有 MyObjectClass 属性,从而允许您删除 setter,但保留 getter。 MyObjectClass 将是不可变的。

    创建一个包含 MyObjectClass 的所有可设置属性的上下文对象。此上下文对象只能传递给 MyObjectClass 构造函数。上下文对象应该在 main 中创建,调用适当的设置器,然后在从 main 实例化时传递到 MyObjectClass。 MyObjectClass 类在内部使用上下文对象的这些属性,但没有它们的设置器。 MyObjectClass 上当然会有可用的 getter,它会从内部上下文对象中获取值。 MyObjectClass 将是不可变的,但这种方式更灵活。

我更喜欢第二种选择。这是一个代码示例:

myClass.h

class MyObjectContext 
public:
    void SetSome(const QList<QString> &value);
    QList<QString> GetSome() const;

private:
    QList<QString> m_myMember;
;

class MyObjectClass 
public:
    MyObjectClass(MyObjectContext *context) : context_(context) 
    QList<QString> GetSome() const return context_->GetSome();

    // Put the rest of the important stuff here

private:
    MyObjectContext *context_;
    MyObjectClass(); // explicitly stating that the default ctor cant be called
;

main.cpp

int main()

    // creating these objects on the stack, you may need
    // to create them dynamically, its up to you
    MyObjectContext context;
    context.SetSome() // This Should work

    MyObjectClass moc(&context);

    MyThread thread(&moc);
    thread.start();

    //..
    return 0;

anyThread.h

class MyThread : public QThread  // Assuming you're inheriting from QThread
public:
    // instead of setting it via the ctor, you could consider adding a setter
    MyThread(MyObjectClass *moc) : moc_(moc) 
    void run();

private:
    MyThread(); // explicitly stating that the default ctor cant be called
    MyObjecctClass *moc_
;

anyThread.cpp

void MyThread::run()

    moc_->GetSome();                  //This should work

    // Dont have to worry about the setters, since there are none
    // available for the MyObjectClass, which is now immutable

【讨论】:

以上是关于多线程设计,保护C++中的全局成员的主要内容,如果未能解决你的问题,请参考以下文章

具有全局变量的 C++ 多线程

c++多线程问题

多线程访问全局变量和局部变量

如何在一个类中执行 C++ 多线程(将线程引用保持为成员 var)

C++中的多线程矩阵乘法

将互斥保护构建到 C++ 类中的线程安全方法?