2010-09-03 18 views
5

मुझे लगातार बनाए गए धागे के निष्पादन के आदेश में कोई समस्या है। यहां कोड है।बढ़ावा :: थ्रेड निष्पादन आदेश

#include <iostream> 
#include <Windows.h> 
#include <boost/thread.hpp> 

using namespace std; 

boost::mutex mutexA; 
boost::mutex mutexB; 
boost::mutex mutexC; 
boost::mutex mutexD; 


void SomeWork(char letter, int index) 
{ 
    boost::mutex::scoped_lock lock; 
    switch(letter) 
    { 
    case 'A' : lock = boost::mutex::scoped_lock(mutexA); break; 
    case 'B' : lock = boost::mutex::scoped_lock(mutexB); break; 
    case 'C' : lock = boost::mutex::scoped_lock(mutexC); break; 
    case 'D' : lock = boost::mutex::scoped_lock(mutexD); break; 
    } 

    cout << letter <<index << " started" << endl; 
    Sleep(800); 
    cout << letter<<index << " finished" << endl; 
} 

int main(int argc , char * argv[]) 
{ 
    for(int i = 0; i < 16; i++) 
    { 
     char x = rand() % 4 + 65; 
     boost::thread tha = boost::thread(SomeWork,x,i); 
     Sleep(10); 
    } 
Sleep(6000); 
    system("PAUSE"); 
    return 0; 
} 

हर बार (डी करने के लिए एक से) एक पत्र और एक genereaion आईडी (i) एक धागे के रूप में विधि SomeWork को पारित कर दिया है। मुझे पत्रों के बीच निष्पादन आदेश की परवाह नहीं है, लेकिन एक प्रख्यात पत्र के लिए, ए कहें, एक्स को पहले से शुरू करना है, यदि x < y। कोड के एक यादृच्छिक उत्पादन के एक यादृच्छिक हिस्सा है:

 
B0 started 
D1 started 
C2 started 
A3 started 
B0 finished 
B12 started 
D1 finished 
D15 started 
C2 finished 
C6 started 
A3 finished 
A9 started 
B12 finished 
B11 started --> B11 started after B12 finished. 
D15 finished 
D13 started 
C6 finished 
C7 started 
A9 finished 

कैसे इस तरह की स्थितियों से बच सकते हैं?
धन्यवाद।


मैंने स्थिति चर का उपयोग कर समस्या हल की। लेकिन मैंने समस्या को थोड़ा सा बदल दिया। समाधान लूप के सूचकांक का ट्रैक रखना है। इसलिए प्रत्येक धागा जानता है कि यह काम नहीं करता है। लेकिन जहां तक ​​इस कोड का सवाल है, वहां दो अन्य चीजें हैं जिन्हें मैं पूछना चाहता हूं।
सबसे पहले, मेरे कंप्यूटर पर, जब मैंने 350 के लिए फॉर-लूप इंडेक्स सेट किया था तो मुझे एक्सेस उल्लंघन था। 310 लूप की संख्या थी, जो ठीक था। इसलिए मुझे एहसास हुआ कि उत्पन्न होने के लिए अधिकतम संख्या में धागे हैं। मैं इस नंबर को कैसे निर्धारित कर सकता हूं? दूसरा, विजुअल स्टूडियो 2008 में, कोड के रिलीज़ संस्करण ने वास्तव में अजीब व्यवहार दिखाया। हालत चर का उपयोग किए बिना (लाइन 1 से 3 टिप्पणी की गई थी), धागे का आदेश दिया गया था। यह कैसे हो सकता है?

यहाँ कोड है: आप दो अलग-अलग लॉक के लिए इंतज़ार कर धागे है, तो

#include <iostream> 
#include <Windows.h> 
#include <boost/thread.hpp> 

using namespace std; 

boost::mutex mutexA; 
boost::mutex mutexB; 
boost::mutex mutexC; 
boost::mutex mutexD; 


class cl 
{ 
public: 
    boost::condition_variable con; 
    boost::mutex mutex_cl; 
    char Letter; 
    int num; 
    cl(char letter) : Letter(letter) , num(0) 
    { 

    } 
    void doWork(int index, int tracknum) 
    { 
     boost::unique_lock<boost::mutex> lock(mutex_cl); 
     while(num != tracknum)  // line 1 
      con.wait(lock); // line 2 
     Sleep(10); 
     num = index; 
     cout << Letter<<index << endl; 
     con.notify_all(); // line 3 
    } 
}; 

int main(int argc , char * argv[]) 
{ 
    cl A('A'); 
    cl B('B'); 
    cl C('C'); 
    cl D('D'); 

    for(int i = 0; i < 100; i++) 
    { 
     boost::thread(&cl::doWork,&A,i+1,i); 
     boost::thread(&cl::doWork,&B,i+1,i); 
     boost::thread(&cl::doWork,&C,i+1,i); 
     boost::thread(&cl::doWork,&D,i+1,i); 
    } 
    cout << "************************************************************************" << endl; 

    Sleep(6000); 
    system("PAUSE"); 
    return 0; 
} 

उत्तर

6

, यह पूरी तरह गैर नियतात्मक जो एक यह अधिग्रहण करेगा लॉक पिछले धारक द्वारा जारी की है है। मेरा मानना ​​है कि आप यही अनुभव कर रहे हैं। मान लें B10 लॉक पकड़ रहा है, और औसत समय धागे B11 और B12 के लिए तैयार किए गए हैं। B10 ताला जारी करता है - यह B11 या B12 के बाद एक सिक्का टॉस पर है, चाहे वह पहले से प्राप्त हो, चाहे वह धागा पहले बनाया गया हो, या यहां तक ​​कि कौन सा थ्रेड पहले इंतजार करना शुरू कर दिया था।

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

+0

कार्य इकाइयों का क्या मतलब है? –

+0

धागे द्वारा किए जाने वाले काम के टुकड़े का कुछ प्रतिनिधित्व। इस मामले में, एक कार्य इकाई मूल रूप से '(पत्र, सूचकांक) 'जोड़ी होगी। – Gian

2

भले ही बी 11 बी 12 से पहले शुरू किया गया है, लेकिन बी 12 से पहले कुछ वर्क() को निष्पादित करने के लिए सीपीयू टाइम स्लाइस दिया जाने की गारंटी नहीं है। यह निर्णय ओएस और उसके शेड्यूलर पर निर्भर है।

म्यूटेक्स आमतौर पर धागे के बीच डेटा तक पहुंच को सिंक्रनाइज़ करने के लिए उपयोग किया जाता है और थ्रेड निष्पादन (यानी डेटा एक्सेस) के अनुक्रम के साथ एक चिंता उठाई गई है।

यदि समूह 'ए' के ​​लिए थ्रेड उसी डेटा पर एक ही कोड निष्पादित कर रहे हैं तो बस एक थ्रेड का उपयोग करें। यह समूह में धागे के बीच संदर्भ स्विचिंग को खत्म कर देगा और एक ही परिणाम देगा। यदि डेटा बदल रहा है तो निर्माता/उपभोक्ता पैटर्न पर विचार करें। पॉल ब्रिजर उत्पादक/उपभोक्ता उदाहरण here समझने में आसान है।

1

आपके धागे की निर्भरताएं हैं जो निष्पादन शुरू करने से पहले संतुष्ट होनी चाहिए। आपके उदाहरण में, बी 12 बी 0 और बी 11 पर निर्भर करता है। किसी भी तरह आपको उस निर्भरता ज्ञान को ट्रैक करना होगा। अधूरा निर्भरताओं के साथ धागे इंतजार करने के लिए किया जाना चाहिए।

मैं condition variables पर देखता हूं। प्रत्येक बार जब थ्रेड कुछ वर्क() को समाप्त करता है तो यह कंडीशन वैरिएबल की notify_all() विधि का उपयोग करेगा। फिर सभी प्रतीक्षा धागे को जांच करनी चाहिए कि क्या उनके पास अभी भी निर्भरता है या नहीं। यदि ऐसा है, तो वापस जाओ और प्रतीक्षा करें। अन्यथा, आगे बढ़ें और SomeWork() पर कॉल करें।

आपको प्रत्येक थ्रेड के लिए यह निर्धारित करने के लिए कुछ तरीका चाहिए कि इसमें अधूरा निर्भरता है या नहीं। यह शायद कुछ वैश्विक रूप से उपलब्ध इकाई होगी। जब आप mutex (SomeWork()) में हों तो आपको केवल इसे संशोधित करना चाहिए। कई धागे द्वारा पढ़ना सरल डेटा संरचनाओं के लिए सुरक्षित होना चाहिए।

संबंधित मुद्दे