2021 시작

스래드를 사용하는데에 동기화를 하는것은 매우 중요하다 안그러면 공유자원을 제대로 쓰지못한다. 그래서 나온것이 동기화이다. 동기화 기법중에 하나인 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()을 만나 동작을 멈춘 스래드가
                             //다시 동작한다.

        }

    }

};

 

 

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading