धागे के भीतर डेटा रखने के बजाय, थ्रेड के बाहर डेटा को स्थानांतरित करें, इसकी रक्षा करें और फिर इसे दोनों धागे से एक्सेस करें।
निम्नलिखित एक स्केच, तो आप क्या कर सकते हैं में से एक है:
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
** आपको इस मामले में एक म्यूटेक्स की आवश्यकता नहीं है। ** आपको लगता है कि प्रत्येक थ्रेड के लिए 2 अलग-अलग कक्षाएं हैं, जैसा कि 'class thread_a' द्वारा सुझाया गया है घोषणा। इसका मतलब यह है कि जब दोनों वर्गों को तत्काल किया जाता है, तो प्रत्येक के पास 'int काउंटर' की अपनी प्रति होगी; और एक वस्तु के 'काउंटर' को कम करने से दूसरे के 'काउंटर' को प्रभावित नहीं होगा। – karlphillip
धन्यवाद @karlphipip, आप सही हैं। लेकिन अगर मैं 'थ्रेड_ए'' और 'थ्रेड_बी' दोनों के साथ 'काउंटर' साझा करना चाहता हूं जो आप सुझाते हैं (शैक्षणिक उद्देश्य के लिए 'क्यूएमयूटीएक्स' का उपयोग करके) –
संभावित डुप्लिकेट [QThread के साथ समस्याएं प्राप्त करने का प्रयास करें] (http://stackoverflow.com/प्रश्न/6084110/क्यूथ्रेड के साथ-साथ-समस्याएं-समस्याएं) – karlphillip