2012-01-23 15 views
13

मैं क्यूटी के लिए नौसिखिया हूं और मैं क्यूटी में बहु-थ्रेडिंग की तलाश में हूं।
जैसा कि मैंने Qt Documents में सीखा है, मैं दो धागे के लिए दो वर्ग में परिभाषित किया गया:QMutex का उपयोग कैसे करें?

#include <QThread> 
#include <QMutex> 

class thread_a : public QThread 
{ 
    Q_OBJECT 
public: 
    explicit thread_a(QObject *parent = 0); 
    int counter; 

protected: 
    void run(); 
}; 

और सीपीपी फ़ाइल में:

#include "thread_a.h" 

thread_a::thread_a(QObject *parent) : 
    QThread(parent) 
{ 
    counter=0; 
} 

void thread_a::run() 
{ 
    counter++; 
} 

दूसरा धागा वर्ग ही है, लेकिन run() विधि में counter-- साथ।
फिर मैं main.ccp से इन दो धागे चलाता हूं।

अब मेरे सवाल:
मैं QMutex का उपयोग कर कैसे साझा कर सकते हैं thread_a और thread_b में counter?

+2

** आपको इस मामले में एक म्यूटेक्स की आवश्यकता नहीं है। ** आपको लगता है कि प्रत्येक थ्रेड के लिए 2 अलग-अलग कक्षाएं हैं, जैसा कि 'class thread_a' द्वारा सुझाया गया है घोषणा। इसका मतलब यह है कि जब दोनों वर्गों को तत्काल किया जाता है, तो प्रत्येक के पास 'int काउंटर' की अपनी प्रति होगी; और एक वस्तु के 'काउंटर' को कम करने से दूसरे के 'काउंटर' को प्रभावित नहीं होगा। – karlphillip

+1

धन्यवाद @karlphipip, आप सही हैं। लेकिन अगर मैं 'थ्रेड_ए'' और 'थ्रेड_बी' दोनों के साथ 'काउंटर' साझा करना चाहता हूं जो आप सुझाते हैं (शैक्षणिक उद्देश्य के लिए 'क्यूएमयूटीएक्स' का उपयोग करके) –

+0

संभावित डुप्लिकेट [QThread के साथ समस्याएं प्राप्त करने का प्रयास करें] (http://stackoverflow.com/प्रश्न/6084110/क्यूथ्रेड के साथ-साथ-समस्याएं-समस्याएं) – karlphillip

उत्तर

25

धागे के भीतर डेटा रखने के बजाय, थ्रेड के बाहर डेटा को स्थानांतरित करें, इसकी रक्षा करें और फिर इसे दोनों धागे से एक्सेस करें।

निम्नलिखित एक स्केच, तो आप क्या कर सकते हैं में से एक है:

class Counter 
{ 
    public: 
    Counter():mMutex(),mCounter(0){} 
    int inc() 
    { 
     QMutexLocker ml(&mMutex); 
     return mCounter++; 
    } 
    int dec() 
     QMutexLocker ml(&mMutex); 
     return mCounter--; 
    } 
    private: 
    QMutex mMutex; 
    int mCounter; 
    Q_DISABLE_COPY(Counter) 
}; 

class ThreadA : public QThread 
{ 
    public: 
    ThreadA(Counter* ctr); 
    /* ... */ 
}; 

class ThreadB : public QThread 
{ 
    public: 
    ThreadB(Counter* ctr); 
    /* ... */ 
}; 

Counter का निर्माण अक्सर एक Monitor रूप में निर्दिष्ट है विकिपीडिया (जोर मेरा) से:

समवर्ती में प्रोग्रामिंग, एक मॉनीटर एक ऑब्जेक्ट या मॉड्यूल है जिसका उद्देश्य एक से अधिक थ्रेड द्वारा सुरक्षित रूप से उपयोग किया जाना है। एक मॉनीटर की परिभाषित विशेषता यह है कि इसकी विधियां आपसी बहिष्कार के साथ निष्पादित की जाती हैं। यही है, समय पर प्रत्येक बिंदु पर, अधिकांश धागे अपने किसी भी तरीके को निष्पादित कर सकते हैं। यह परस्पर बहिष्करण डेटा संरचना अद्यतन करने वाले समानांतर कोड के तर्क के मुकाबले मॉनीटर के कार्यान्वयन के बारे में तर्क को सरल बनाता है।

इस विशिष्ट मामले में, एक और अधिक कुशल निर्माण QAtomicInt होगा। यह विशेष CPU निर्देशों के उपयोग से परमाणुता प्राप्त करता है। यह एक निम्न स्तर की कक्षा है जिसका उपयोग अन्य थ्रेडिंग संरचनाओं को लागू करने के लिए किया जा सकता है।


संपादित करें - संपूर्ण उदाहरण

सही ढंग से साझा राज्य के साथ धागे का उपयोग करना तुच्छ नहीं है। आप कतार कनेक्शन या अन्य संदेश आधारित सिस्टम के साथ क्यूटी संकेत/स्लॉट का उपयोग करने पर विचार करना चाह सकते हैं।

वैकल्पिक रूप से, अन्य प्रोग्रामिंग भाषाएं जैसे एडा समर्थन थ्रेड और मॉनीटर (संरक्षित ऑब्जेक्ट्स) देशी संरचनाओं के रूप में।

यहां एक पूर्ण कार्य उदाहरण है। यह केवल नमूना कोड है, वास्तविक कोड में QTest::qSleep का उपयोग न करें।

objs.h

#ifndef OBJS_H 
#define OBJS_H 

#include <QtCore> 

class Counter 
{ 
    public: 
     Counter(int init); 
     int add(int v); 
    private: 
     QMutex mMutex; 
     int mCounter; 
     Q_DISABLE_COPY(Counter) 
}; 

class CtrThread : public QThread 
{ 
    Q_OBJECT 
    public: 
     CtrThread(Counter& c, int v); 
     void stop(); 
    protected: 
     virtual void run(); 
    private: 
     bool keeprunning(); 
     Counter& mCtr; 
     int mValue; 
     bool mStop; 
     QMutex mMutex; 
}; 

#endif 

objs।सीपीपी

#include "objs.h" 

Counter::Counter(int i): 
    mMutex(), 
    mCounter(i) 
{} 

int Counter::add(int v) 
{ 
    QMutexLocker ml(&mMutex); 
    return mCounter += v; 
} 

/////////////////////////////////////// 

CtrThread::CtrThread(Counter& c, int v): 
    mCtr(c), 
    mValue(v), 
    mStop(false), 
    mMutex() 
{} 

void CtrThread::stop() 
{ 
    QMutexLocker ml(&mMutex); 
    mStop = true; 
} 

void CtrThread::run() 
{ 
    while(keeprunning()) 
    { 
     mCtr.add(mValue); 
    } 
} 

bool CtrThread::keeprunning() 
{ 
    QMutexLocker ml(&mMutex); 
    return ! mStop; 
} 

test.cpp

#include <QtCore> 
#include <QTest> 
#include "objs.h" 

int main(int argc, char** argv) 
{ 
    QCoreApplication app(argc, argv); 

    qDebug() << "Initalising"; 

    Counter ctr(0); 
    CtrThread thread_a(ctr, +1); 
    CtrThread thread_b(ctr, -1); 

    qDebug() << "Starting Threads"; 

    thread_a.start(); 
    thread_b.start(); 

    for (int i = 0; i != 15; ++i) 
    { 
     qDebug() << "Counter value" << ctr.add(0); 
     QTest::qSleep(1000); 
    } 

    qDebug() << "Stopping Threads"; 

    thread_a.stop(); 
    thread_b.stop(); 
    thread_a.wait(); 
    thread_b.wait(); 

    qDebug() << "Finished"; 
    return 0; 
} 

test.pro

QT=core testlib 
HEADERS=objs.h 
SOURCES=test.cpp objs.cpp 

संकलित करें और चलाने के लिए, आप मूल्य देखेंगे मुद्रित किया जा रहा है, नमूना उत्पादन:

Initalising 
Starting Threads 
Counter value 0 
Counter value 11057 
Counter value 28697 
Counter value 50170 
Counter value 60678 
Counter value 73773 
Counter value 84898 
Counter value 96441 
Counter value 118795 
Counter value 135293 
Counter value 146107 
Counter value 158688 
Counter value 169886 
Counter value 201203 
Counter value 212983 
Stopping Threads 
Finished 
+0

हे @skyhisi महान समाधान के लिए धन्यवाद ... लेकिन मैं सिर्फ शिक्षा उद्देश्य के लिए 'QMutex' की तलाश में हूं। मैं क्यूटी चरण-दर-चरण में बहु-थ्रेडिंग सीखना चाहता हूं। क्या आप मुझे QMutex का उपयोग करके एक सरल कार्यान्वयन दे सकते हैं (दो धागे पर 'काउंटर' साझा करने के लिए) –

3

ठीक है, असली परियोजना के लिए महान समाधान के लिए @skyhisi के लिए विशेष धन्यवाद।

मैंने @skyhisi पोस्ट और QMutex और साझा करने वाले चर के बारे में अधिक लेख पढ़े। शिक्षा के उद्देश्य के लिए मैंने परिवर्तनीय साझा करने के लिए QMutex उपयोग का एक सरल/स्पष्ट नमूना लागू किया (यह मामला counter)।

class thread_a : public QThread 
{ 
    Q_OBJECT 
public: 
    thread_a(QMutex*, int*); 
    void shutdown(); 

private: 
    QMutex* mutex; 
    int* counter; 
    bool isShutdownRequested; 

protected: 
    void run(); 
}; 

और thread_a.cpp फ़ाइल में:

thread_a::thread_a(QMutex * m, int* i) 
{ 
    counter=i; 
    isShutdownRequested=false; 
    mutex=m; 
} 

void thread_a::run() 
{ 
    isShutdownRequested=false; 
    forever{ 
     //lock mutex for changing in shared variable 
     mutex->lock(); 
     *counter=*counter+1; 
     mutex->unlock(); 

     if(isShutdownRequested) 
      break; 
    } 
} 

void thread_a::shutdown() 
{ 
    isShutdownRequested=true; 
} 

myMainWindow::RunThreads(bool bl) में स्लॉट:

int cnt=0; 
QMutex mu; 
thread* a=new thread_a(&mu, &cnt); 
thread* b=new thread_b(&mu, &cnt); 
a.start(); 
b.start(); 

myMainWindow::~myMainWindow() Deconstructor में:

a->shutdown(); 
b->shutdown(); 

धन्यवाद फिर से @skyh आईएसआई

1

मैं QMutex की "सहायता" के संदर्भ में एक साधारण उदाहरण लिखता हूं, जिसमें दो धागे एक ही संख्या (मॉनिटर के रूप में) को बदलते हैं। यह एसएम मूसवी के कोड को भी रेफरी करता है। यहाँ कोड है:

//main.cpp

#include <QCoreApplication> 
#include "method.h" 

int aNum=0; 
QMutex aMutex; 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    int *p_no= &aNum; 
    QMutex *p_Mu = &aMutex; 

    method mThread1(p_Mu, p_no); 
    method mThread2(p_Mu, p_no); 

    mThread1.name = "one"; 
    mThread2.name = "two"; 

    mThread1.start(); 
    mThread2.start(); 

    return a.exec(); 
} 

// method.h

#ifndef METHOD_H 
#define METHOD_H 

#include <QDebug> 
#include <QThread> 
#include <QtCore> 
#include <QString> 
#include <QMutex> 


class method: public QThread 
{ 
public: 
    method(QMutex *mu, int *nu); 
    void run(); 
    void method1(); 
    void method2(); 
    QString name; 

private: 
    int *number; 
    QMutex *myMutex; 
}; 

#endif // METHOD_H 

//method.cpp #include "method.h"

method::method(QMutex *mu, int *nu) 
{ 
    myMutex = mu; 
    number = nu; 
} 


void method:: run() 
{ 
    for (int i = 0; i<100; i++) 
    { 
     if(this->name == "one") 
     { 
      this->method1(); 
     } 
     else 
     { 
      this->method2(); 
     } 
    } 
} 

void method::method1() 
{ 
    myMutex->lock(); 
    *number += 1; 
    qDebug()<<*number<<"---"<<this->name; 
    myMutex->unlock(); 
} 

void method ::method2() 
{ 
    myMutex->lock(); 
    *number -= 1; 
    qDebug()<<*number<<"---"<<this->name; 
    myMutex->unlock(); 
} 
संबंधित मुद्दे