2013-07-02 7 views
8

मैं वर्तमान में एक समस्या पर काम कर रहा हूं जो एक विस्तारित निर्माता-कार्यकर्ता मॉडल को अनुकरण करता है। इस समस्या में 3 श्रमिक और 3 उपकरण उपलब्ध हैं, और श्रमिकों के काम करने के लिए उन्हें 2 औजारों की आवश्यकता है (और सामग्री लेकिन वे अप्रासंगिक हैं)। यदि वॉल्ट में> = 2 टूल्स हैं, तो एक कर्मचारी 2 ले जाएगा। अन्यथा, वे एक कंडीशन वैरिएबल पर इंतजार करेंगे जो> = 2 होने पर संकेतित किया जाएगा।सी ++ 11 थ्रेड: एकाधिक थ्रेड एक शर्त चर पर प्रतीक्षा कर रहे हैं

यह 2 श्रमिकों के साथ ठीक है: कोई काम करेगा, फिर उपकरण को वॉल्ट पर वापस कर देगा, और दूसरा प्रतीक्षा कार्यकर्ता जाग जाएगा और 2 टूल्स लेगा। समस्या यह है कि, 3 श्रमिकों के साथ, हमेशा उपकरण प्राप्त करने के लिए एक भूख लगी होगी।

कुछ परीक्षणों के बाद मैंने देखा है कि एक शर्त चर के लिए प्रतीक्षा करने वाले थ्रेड स्टैक फॉर्म में संरचित हैं। क्या यह कतारबद्ध रूप बनाने के लिए वैसे भी संभव है? (1 इंतजार, 2 इंतजार, और 3 इंतजार कर रहा है। जब 1 जाग गया है और दूसरा बनाना चाहता है, तो उसे 2 और 3 के पीछे इंतजार करना होगा।

यहां एक नमूना आउटपुट है। कोड बहुत लंबा है इसलिए यदि यह वास्तव में आवश्यक है तो मैं इसे पोस्ट करूंगा। 3 कार्यकर्ता धागे और 1 उपकरण म्यूटेक्स हैं। जो भी भूखा है वह हर दूसरे भाग को अलग करता है।

1 Tools taken. Remaining: 1 
2 Waiting on tools... 
3 Waiting on tools... 
1 Operator Product made. Tools returned. Tools now:3 
3 Tools taken. Remaining: 1 
1 Waiting on tools... 
3 Materials returned for switch. 
3 Operator Product made. Tools returned. Tools now:3 
1 Tools taken. Remaining: 1 
3 Waiting on tools... 
1 Materials returned for switch. 
1 Operator Product made. Tools returned. Tools now:3 
3 Tools taken. Remaining: 1 
1 Waiting on tools... 
3 Materials returned for switch. 
3 Operator Product made. Tools returned. Tools now:3 
1 Tools taken. Remaining: 1 
3 Waiting on tools... 
1 Materials returned for switch. 
1 Operator Product made. Tools returned. Tools now:3 
3 Tools taken. Remaining: 1 
1 Waiting on tools... 
3 Materials returned for switch. 
3 Operator Product made. Tools returned. Tools now:3 
1 Tools taken. Remaining: 1 
3 Waiting on tools... 
1 Materials returned for switch. 
... 

(आप देख सकते हैं 2 उपकरण हो जाता है कभी नहीं ...)

अद्यतन: 2013/07/05 मैं कुछ कोड जोड़ लिया है।

int tools = 3; //global 
string last; //current last product on output buffer 
mutex toolsMutex; 
mutex matSearchMutex; 

int main(){ 
//Initializing Producers 
    Producer prod1(1); 
    Producer prod2(2); 
     Producer prod3(3); 



    thread p1(processor,1); 
    thread p2(processor,2); 
    thread p3(processor,3); 

    p1.detach(); 
    p2.detach(); 
    p3.detach(); 

    while(true){//forever running 

    } 

    return 0; 
} 

प्रोसेसर:

//Processor method 
void processor(int i){ 
    srand(time(NULL)); 

    while (true){ //forever running 


    bool hasTools = false; 
    bool productMade = false; 
    while (productMade == false){ //while product has yet to be made. 
     //choose what to make... 



     if (hasTools == false){ 
      thread matT(getMaterials,whatToMake); 
      thread toolT(getTools,i); 
      toolT.join();   
      matT.join(); 
      hasTools = true; 
     } 
     else{ //tools acquired but no materials 
      thread matT(getMaterials,whatToMake); 
      matT.join(); 
     } 

     if (recordedLast.compare(last) != 0){ 

      //return materials and acquire new ones the next run 

      continue; 
     } 
     else { 
      makeProduct(whatToMake); 
      unique_lock<mutex> locker(toolMutex); 
      tools = tools + 2; 
      cout << i << " Operator Product made. Tools returned. Tools now:" << tools << endl; 
      productMade = true; 
      if (tools >=2) toolsCV.notify_one(); 
     } 

    //done processing 

    } 


} 

} 

makeProducts:

void makeProduct(int i){ 
    unique_lock<mutex> mainMatLock(matSearchMutex); 
    // make product according to i 
    this_thread::sleep_for(chrono::milliseconds(rand() % 1000 + 10)); 
} 

getTools:

void getTools(int i){ 
    unique_lock<mutex> locker(toolMutex); 
    if (tools <2){ 
     cout << i << " Waiting on tools..." << endl; 
     toolsCV.wait(locker);} 
    tools = tools - 2;//tools acquired 
    cout << i <<" Tools taken. Remaining: " << tools << endl; 

} 

जो लोग जवाब दिया है के लिए धन्यवाद। मैं कई हालत चर का उपयोग कर आज रात एक प्रतीक्षा कतार लागू करने की कोशिश करूंगा।

(पी एस वहाँ कोड स्टैक ओवरफ़्लो पर यहाँ स्वरूपण? चार रिक्त स्थान के अलावा करने के लिए कुछ बेहतर तरीका ...

+0

आप अपना वास्तविक कोड क्यों नहीं पोस्ट करते? क्या आपने कंडीशन वैरिएबल (बनाम सिग्नल) पर प्रसारण करने की कोशिश की है? आप अपने पर्यावरण के बारे में कुछ भी निर्दिष्ट किया है नहीं है, लेकिन http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_04_01 से अधिक एक आँख कास्ट करने के लिए चाहते हो सकता है –

+1

_ "वहाँ कोड करने के लिए कुछ बेहतर तरीका है स्टैक ओवरफ़्लो पर यहाँ स्वरूपण? "_ बिना रिक्त स्थान तो पूरे कोड ब्लॉक और Ctrl-कश्मीर पर प्रकाश डाला या प्रेस कोड दर्ज ** {} ** संपादन बॉक्स के ऊपर टूलबार में बटन –

उत्तर

9

std::condition_variable निर्दिष्ट नहीं करता जो प्रतीक्षा धागा जगाया जाता है जब आप notify_one कहते हैं। इसलिए आपको कोड लिखना चाहिए जो परवाह नहीं करता कि कौन सा धागा जाग गया है। मानक पैटर्न यह है कि जो भी धागा जागृत होता है, वह थ्रेड उस काम को करना चाहिए जिसे करने की आवश्यकता है।

यदि आपको आवश्यकता है कि धागे किसी विशिष्ट क्रम में जागृत हों, तो एक अलग तंत्र का उपयोग करें। उदाहरण के लिए, आप प्रत्येक थ्रेड के लिए अलग std::condition_variable कर सकते हैं, और फिर थ्रेड को कतार में रखकर उन्हें उपकरण की आवश्यकता होती है। उपकरण में धागे के हाथों के रूप में, यह कतार के सामने थ्रेड से संबंधित स्थिति चर को सिग्नल कर सकता है। तब वह धागा जाग जाएगा, और बाकी सो रहे होंगे (मॉड्यूलो नकली जागने)।

3

जब कई धागे एक शर्त पर इंतजार कर रहे हैं, ताकि जिसमें वे जागृत कर रहे हैं (notify_all) या जो एक जागृत है (notify_one) अनिर्दिष्ट है आप किसी प्रकार का आदेश देने की की जरूरत है, आप अपने आप को notify_all का उपयोग, और यह लागू करने के लिए आप धागे इंतजार कर के एक कतार रख सकते की जरूरत है:।। इंतज़ार कर से पहले (लेकिन म्यूटेक्स प्राप्त करने के बाद), थ्रेड आईडी को पर कतार के अंत में दबाएं। लूप में, लूप पर "यह धागा कतार के सामने और आवश्यक उपकरण उपलब्ध है"। जब आपको उपकरण मिलते हैं, तो कतार के सामने से आईडी हटा दें, और notify_all पर दोबारा कॉल करें।

0

एक दृष्टिकोण एक पूरी तरह से विकसित सेमफोर का उपयोग करना हो सकता है जो एक शर्त चर के बजाय धागे के बीच साझा किया जाता है। इस तरह, आप एक विशिष्ट गणना के लिए इंतजार कर सकते हैं।

#include <mutex> 
#include <thread> 
#include <condition_variable> 

using std::mutex; 
using std::condition_variable; 

class Semaphore 
{ 
public: 
    /** 
    * Construct a counting semaphore with an initial value 
    * @param cnt The value of the initial semaphore count 
    */ 
    Semaphore(unsigned int cnt); 

    /** 
    * acquire a semaphore count 
    * @param numRes The number of count ressources to acquire 
    */ 
    void acquire(unsigned int numRes = 1); 

    /** 
    * try to acquire a semaphore count. 
    * @param numRes The number of count ressources that the method tries to acquire 
    * @return true, if numRes could be aquired 
    *   false, otherwise 
    */ 
    bool tryAcquire(unsigned int numRes = 1); 

    /** 
    * release one semaphore cnt 
    * @param numRes The number of count ressources to release 
    */ 
    void release(unsigned int numRes = 1); 

private: 
    unsigned int cnt; 
    mutex mut; 
    condition_variable cond; 
}; 

कार्यान्वयन लगता है:

void Semaphore::acquire(unsigned int numRes) 
{ 
    unique_lock<mutex> lock(mut); 
    while (cnt < numRes) 
    { 
     cond.wait(lock); 
    } 

    cnt-=numRes; 
} 

bool Semaphore::tryAcquire(unsigned int numRes) 
{ 
    unique_lock<mutex> lock(mut); 
    if (cnt>=numRes) 
    { 
     cnt -= numRes; 
     return true; 
    } 
    return false; 
} 

void Semaphore::release(unsigned int numRes) 
{ 
    { 
     unique_lock<mutex> lock(mut); 
     cnt += numRes; 
    } 
    // notify <numRes> waiting entities 
    for (unsigned int i = 0; i<numRes; ++i) 
    { 
     cond.notify_one(); 
    } 
} 
1

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

यदि यह आपके लिए ठीक नहीं है, तो आपको अन्य उत्तरों में बताए गए कार्यों को स्वयं लेना होगा।

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