스래드를 사용하는데에 동기화를 하는것은 매우 중요하다 안그러면 공유자원을 제대로 쓰지못한다. 그래서 나온것이 동기화이다. 동기화 기법중에 하나인 mutex를 써보자
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
static int num_data;
static QMutex mutex;
class MyThread1 : public QThread
{
Q_OBJECT
private:
void run() override
{
for(int i=0;i<10;i++)
{
mutex.lock(); //mutex를 lock한다 그러면 해당 뮤텍스 객체를
//쓰는 스래드는 똑같은 mutex객체의 lock()함수를 만나자 마자
//동작을 멈춘다.
++num_data; //num_data를 1 더한다.
qDebug()<<QString("MyThread1 : %1").arg(num_data); //num_data출력
mutex.unlock(); //mutex를 unlock한다.
//똑같은 mutex객체의 lock()을 만나 동작을 멈춘 스래드가
//다시 동작한다.
}
}
};
class MyThread2 : public QThread
{
Q_OBJECT
private:
void run() override
{
for(int i=0;i<10;i++)
{
mutex.lock(); //mutex를 lock한다 그러면 해당 뮤텍스 객체를
//쓰는 스래드는 똑같은 mutex객체의 lock()함수를 만나자 마자
//동작을 멈춘다.
qDebug()<<QString("MyThread2 : %1").arg(num_data);//num_data출력
mutex.unlock(); //mutex를 unlock한다.
//똑같은 mutex객체의 lock()을 만나 동작을 멈춘 스래드가
//다시 동작한다.
}
}
};
깔끔하게 출력된다. 그런데 만약 MyThread1 클래스에 Sleep함수가 있으면 어떻게 될까?
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
static int num_data;
static QMutex mutex;
class MyThread1 : public QThread
{
Q_OBJECT
private:
void run() override
{
for(int i=0;i<10;i++)
{
///////////////////////////////////
sleep(1); //1초 멈춘다 <--------------추가된 부분
/////////////////////////////////////
mutex.lock(); //mutex를 lock한다 그러면 해당 뮤텍스 객체를
//쓰는 스래드는 똑같은 mutex객체의 lock()함수를 만나자 마자
//동작을 멈춘다.
++num_data; //num_data를 1 더한다.
qDebug()<<QString("MyThread1 : %1").arg(num_data); //num_data출력
mutex.unlock(); //mutex를 unlock한다.
//똑같은 mutex객체의 lock()을 만나 동작을 멈춘 스래드가
//다시 동작한다.
}
}
};
class MyThread2 : public QThread
{
Q_OBJECT
private:
void run() override
{
for(int i=0;i<10;i++)
{
mutex.lock(); //mutex를 lock한다 그러면 해당 뮤텍스 객체를
//쓰는 스래드는 똑같은 mutex객체의 lock()함수를 만나자 마자
//동작을 멈춘다.
qDebug()<<QString("MyThread2 : %1").arg(num_data);//num_data출력
mutex.unlock(); //mutex를 unlock한다.
//똑같은 mutex객체의 lock()을 만나 동작을 멈춘 스래드가
//다시 동작한다.
}
}
};
이렇게 MyThread2가 인정사정없이 이상하게 동작해버린다. 그래서 사용하는것이 QWaitCondition이다.
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
static int num_data;
static QMutex mutex;
static QWaitCondition waitCondition;
class MyThread1 : public QThread
{
Q_OBJECT
private:
void run() override
{
for(int i=0;i<10;i++)
{
///////////////////////////////////
sleep(1); //1초 멈춘다 <--------------추가된 부분
/////////////////////////////////////
mutex.lock(); //mutex를 lock한다 그러면 해당 뮤텍스 객체를
//쓰는 스래드는 똑같은 mutex객체의 lock()함수를 만나자 마자
//동작을 멈춘다.
++num_data; //num_data를 1 더한다.
qDebug()<<QString("MyThread1 : %1").arg(num_data); //num_data출력
waitCondition.wakeAll();//해당 QWaitCondition객체의 wait함수로 멈춰있는
//모든 스래드에 wakeup신호를 보낸다.
mutex.unlock(); //mutex를 unlock한다.
//똑같은 mutex객체의 lock()을 만나 동작을 멈춘 스래드가
//다시 동작한다.
}
}
};
class MyThread2 : public QThread
{
Q_OBJECT
private:
void run() override
{
for(int i=0;i<10;i++)
{
mutex.lock(); //mutex를 lock한다 그러면 해당 뮤텍스 객체를
//쓰는 스래드는 똑같은 mutex객체의 lock()함수를 만나자 마자
//동작을 멈춘다.
waitCondition.wait(&mutex);//인자로 넘긴 mutex객체를 unlock해주고
//wakeup신호를 받을때까지 멈춘다.
qDebug()<<QString("MyThread2 : %1").arg(num_data);//num_data출력
mutex.unlock(); //mutex를 unlock한다.
//똑같은 mutex객체의 lock()을 만나 동작을 멈춘 스래드가
//다시 동작한다.
}
}
};