c ++ qthread запускает 2 потока одновременно - PullRequest
1 голос
/ 08 марта 2011

У меня есть две темы, одна и две. определяется их соответствующими классами в заголовочном файле. Я хочу запустить второй поток при запуске первого потока. создание и запуск второго потока в конструкторе первого дал неожиданный результат. мой заголовочный файл "header.h"

#ifndef HEADER
#define HEADER
#include <QtGui>
class One:public QThread
{
public:
    One();
    void run();

};

class Two:public QThread
{
public:
    Two();
    void run();
};
#endif

файл моего класса "main.cpp"

#include "header.h"
#include<iostream>
using namespace std;

One::One()
{
/* the output just hangs at thread two and does not get to thread one run */
Two b;
b.start();
b.wait();

}
void One::run()
{
    cout<<"One run\n";
    int i=0;
    for(;;)
    {

        i++;
        cout<<"+++ "<<i<<endl;
        if(i==10)
            break;
        sleep(3);
    }
}

Two::Two()
{

}
void Two::run()
{

    cout<<"Two run\n";
    int i=0;
    for(;;)
    {

        i--;
        cout<<"----- "<<i<<endl;
        sleep(3);
    }
}
int main(int argc,char* argv[])
{
    One a;
   // Two b;
    a.start();
   // b.start();
   a.wait();
   // b.wait();
    return(0);

}

Это рабочий код того, как я ожидаю запуска вывода.

Редактировать: изменил код, чтобы теперь обе темы правильно независимый

Как запустить второй поток вместе с первым потоком, без явного вызова двух в основном, т. Е.

int main(int argc,char* argv[])
{
     One a;
    Two b;
    a.start();
    b.start();
    a.wait();
    b.wait();
   return(0);
}

Вызов и обработка потока два должны выполняться потоком один ..

1 Ответ

6 голосов
/ 08 марта 2011

Я полагаю, вы, возможно, неправильно поняли некоторые концепции потоков. Звучит так, как будто вы хотите запустить два потока, а затем из одного контекста потока вызвать функцию в другой контекст потока, а это не то, как работают потоки.

Когда вы запускаете эти два потока, они выполняются независимо друг от друга. Они могут делиться доступом к данным, но вы не можете переплетать их выполнение так, как вам этого хочется. Если вы хотите, чтобы один поток выполнял что-то по запросу другого, у вас есть два решения для двух вещей:

  • Какой механизм использовать для передачи запроса от одного потока к другому
  • Должен ли запрашивающий поток остановиться и подождать "квитанцию" или просто счастливо продолжить, пока другой поток делает то, что ему было предложено.

A очень простой (и не совсем безопасный, просто иллюстрирующий логику) механизм, позволяющий сделать это, используя два bools для сигнализации о запросе, например:

Thread one starts                         | Thread two starts
Thread one works                          | Thread two loops checking a `bool DoSomething;`
Thread one sets bool DoSomething          | 
Thread one loops waiting for DidSomething | Thread two beeps
                                          | Thread two sets DidSomething
Thread one continues working              | 

Следует отметить, что между контекстами потоков нет "вызовов". Два потока выполняются одновременно и обмениваются данными, используя данные (два объекта bools).

В реальной многопоточности вам нужно беспокоиться об одновременном доступе к данным. Что бы, например, произойдет, если два потока одновременно на двухъядерном компьютере попытались добавить данные в один и тот же список. Оба потока могут видеть один и тот же «указатель конца списка», оба будут создавать новую запись, оба обновят «указатель конца списка». Но одно из изменений перезапишет другое, и в лучшем случае у вас будут некоторые потерянные данные и утечка памяти, а в худшем - сбой.

Здесь вы используете механизм «взаимного исключения»: каждый поток, прежде чем получить доступ к такому общему ресурсу, как список, получит мьютекс. Мьютекс сконструирован таким образом, что его может «владеть» только один поток за раз. Если первый поток получит мьютекс первым, он продолжит обновление списка, а затем отпустит мьютекс. В то же время, другие потоки, пытающиеся получить мьютекс, будут просто сидеть, вызов Mutex :: acqu () не будет возвращаться, пока один поток не будет завершен с мьютексом. Если оба потока ведут себя хорошо и получают мьютекс перед доступом к общему списку, описанного выше одновременного обновления не произойдет, и список будет полностью действительным после того, как оба потока обновили его.

В ответ на комментарии:

Вы не можете запустить два потока одновременно. Ближайшим приближением было бы создание и запуск Two из One :: run:

void One::run()
{
    Two b;
    b.start();
    cout<<"One run\n";
    int i=0;
    for(;;)
    {

        i++;
        cout<<"+++ "<<i<<endl;
        if(i==10)
            break;
        sleep(3);
    }
    b.wait();
}
...