线程是否共享某些类字段?

时间:2014-12-11 09:46:10

标签: c++ multithreading qt thread-safety

这是使用Qt 4进行C ++ GUI编程的一个例子

我有一个线程类:

    class Thread : public QThread {

    Q_OBJECT

    public:
        Thread();
        void setMessage(const QString &message);
        void stop();

    protected:
        void run();

    private: 
        QString messageStr;
        volatile bool stopped;

}

这是该课程的相关实施:

Thread::Thread() {
    stopped = false;
}

void Thread::run() {

    while (!stopped)
        std::cerr << qPrintable(messageStr);
    stopped = false;
    std::cerr << std::endl;

}

void Thread::stop() {  
    stopped = true;   
}

此类用于ThreadDialog类,它基本上有两个私有字段Thread threadA和Thread threadBsetMessage函数分别为它们调用,messageStr设置为&#34; A&#34;和&#34; B&#34;。内部声明了两个按钮,其中点击信号连接两个插槽功能,启动或停止这两个线程,如下所示:

void ThreadDialog::startOrStopThreadA() {

    if (threadA.isRunning()) {
        threadA.stop();
        threadAButton->setText(tr("Start A"));
    } else {
        threadA.start();
        threadAButton->setText(tr("Stop A"));
    }

}

threadB的功能是相同的。问题在于,直接引用本书:&#34;已停止的变量被声明为volatile,因为它是从不同的线程访问的,我们希望确保每次需要时都会重新读取它。如果省略volatile关键字,编译器可能会优化对变量的访问,可能导致错误的结果。&#34;

我无法理解为什么这两个线程会访问同一个字段。 Aren他们是不同的实例,所以他们有自己的字段stopped?此外,如果共享stopped字段,为什么还没有共享messageStr字段?

3 个答案:

答案 0 :(得分:0)

这是多线程中常见的混淆。您将线程对象class Thread : public QThread与执行线程(即执行指令)混淆。

  • 有一个执行线程正在运行代码ThreadDialog::startOrStopThreadA
  • 另一个执行线程正在运行Thread::run(),由threadA.start()启动。

这两个主题都可以访问messageStrstopped

答案 1 :(得分:0)

  

我无法理解为什么这两个线程会访问同一个字段。他们不是不同的例子   所以他们有自己的领域停止?此外,如果共享停止字段,为什么不是messageStr   领域也分享了吗?

这不是他们所说的。无论是否涉及线程,该字段都不在不同实例之间共享。但是,可以从不同的线程访问实例,在这方面,字段可能在不同的线程之间“共享”。

他们正在谈论其他线程希望调用threadA.stop()

的情况

如果您有此代码:

Thread threadA;
threadA.start();
... 
threadA.stop();

涉及2个主题:

  1. 运行上述代码的线程
  2. threadA调用
  3. 开头的新创建的threadA.start()

    现在volatile bool stoppedrun()函数中的线程2访问,并且在调用threadA.stop()时从线程1访问它。

答案 2 :(得分:0)

两个实例threadAthreadB不共享stopped。如果是同一个类,它们是不同的实例。

关于本声明:

  

已停止的变量被声明为volatile,因为它是从中访问的   不同的线程,我们希望确保它每次都是新鲜的   时间需要。

这意味着从两个不同的运行线程访问stopped变量。这里两个线程是主应用程序线程和run()函数中的线程。从两个不同的线程访问同一个变量是不安全的。