2010-12-06 17 views
13

मैं अगर एक म्युटेक्स बंद कर दिया या एक अगर बयान में अनलॉक हो गया है देखने के लिए तो मैं इसे इस तरह की जांच की जरूरत है ...जांच करें,

if(mutex[id] != 2){ 
    /* do stuff */ 
} 

लेकिन जब मैं जाँच यह जीसीसी मुझे निम्न त्रुटि देता है:

error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')

तो मैं अगर म्युटेक्स या अवरोधित नहीं है देखने के लिए जाँच कर सकते हैं?

संपादित करें:

मेरी समस्या का एक प्रमुख घटक है कि मेरे धागे (डिजाइन) के द्वारा खुद को सही एक और धागा करने के लिए नियंत्रण पास करने के बाद ताला है। तो जब थ्रेड ए थ्रेड बी थ्रेड ए पर नियंत्रण पास करता है, तो थ्रेड बी कुछ सामान करता है, फिर जब थ्रेड बी किया जाता है तो यह थ्रेड ए अनलॉक करेगा।

समस्या यह है कि अगर थ्रेड बी थ्रेड ए को अनलॉक करने का प्रयास करता है और थ्रेड ए ने अभी तक लॉकिंग पूरी नहीं की है, तो अनलॉक करने के लिए कॉल खो गया है और थ्रेड ए लॉक हो गया है जो मृत लॉक का कारण बनता है।

अद्यतन:

मैं पुनर्निर्माण मेरा कार्यक्रम CAF के सुझाव लेने लेकिन मैं अभी भी समस्या हो रही हूँ। मैंने अपने कार्यक्रम को संरचना कैफ में ढाला है जो कि मैं सबसे अच्छा कर सकता हूं लेकिन मैं यह भी नहीं बता सकता कि अब मृत लॉक का कारण क्या है ... मैंने अपने कोड के साथ मदद के लिए here नया प्रश्न बनाया है।

नीचे कैफ के सुझाव का एक चलने योग्य संस्करण है। मैंने थ्रेड ए के लिए फ़ंक्शन में एक छोटी सी रीडरिंग की, जिसके बिना दोनों थ्रेड ए और थ्रेड बी को उनके निर्माण पर बंद कर दिया गया था, ऐसी स्थिति की प्रतीक्षा करनी जो कभी नहीं बदली।

#include <pthread.h> 

int run_a = 0; 
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER; 

int run_b = 0; 
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER; 

void *a(void *); 
void *b(void *); 

int main(){ 
    int status; 
    pthread_t thread_a; 
    pthread_t thread_b; 

    pthread_create(&thread_a, NULL, a, (void *)0); 
    pthread_create(&thread_b, NULL, b, (void *)0); 

    pthread_join(thread_a, (void **)&status); 
    pthread_join(thread_b, (void **)&status); 

} 

/* thread A */ 
void *a(void *i){ 
    while (1) { 
     printf("thread A is running\n"); 
     sleep(1); 

     /* unlock thread B */ 
     pthread_mutex_lock(&lock_b); 
      run_b = 1; 
      pthread_cond_signal(&cond_b); 
     pthread_mutex_unlock(&lock_b); 

     /* wait for thread A to be runnable */ 
     pthread_mutex_lock(&lock_a); 
      while (!run_a) 
       pthread_cond_wait(&cond_a, &lock_a); 
      run_a = 0; 
     pthread_mutex_unlock(&lock_a);  
    } 
} 

/* thread B */ 
void *b(void *i){ 
    while (1) { 
     /* wait for thread B to be runnable */ 
     pthread_mutex_lock(&lock_b); 
      while (!run_b) 
       pthread_cond_wait(&cond_b, &lock_b); 
      run_b = 0; 
     pthread_mutex_unlock(&lock_b); 

     printf("thread B is running\n"); 
     sleep(1); 

     /* unlock thread A */ 
     pthread_mutex_lock(&lock_a); 
      run_a = 1; 
      pthread_cond_signal(&cond_a); 
     pthread_mutex_unlock(&lock_a); 
    } 
} 
+0

एक त्वरित नोट, म्यूटेक्स को थ्रेड द्वारा अनलॉक किया जाना चाहिए जो उन्हें बंद कर देता है। यदि आप एक लॉकिंग निर्माण चाहते हैं जिसे एक थ्रेड द्वारा लॉक किया जा सकता है और दूसरे द्वारा अनलॉक किया जा सकता है, तो आपको सेमफोर का उपयोग करना होगा (या उपरोक्त उदाहरण में दिखाए गए अनुसार अपना स्वयं का सेमफोर बनाएं)। वास्तव में बदसूरत सिंक्रनाइज़ेशन बग फसल कर सकते हैं यदि एक थ्रेड एक म्यूट को लॉक करता है और दूसरा इसे –

उत्तर

16

म्यूटेक्स इस योजना के लिए सही आदिम नहीं हैं जिसे आप कार्यान्वित करना चाहते हैं।

int run_thread_a = 0; 
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER; 

int run_thread_b = 0; 
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER; 

/* thread A */ 
while (1) { 
    /* Wait for Thread A to be runnable */ 
    pthread_mutex_lock(&run_lock_a); 
    while (!run_thread_a) 
     pthread_cond_wait(&run_cond_a, &run_lock_a); 
    run_thread_a = 0; 
    pthread_mutex_unlock(&run_lock_a); 

    /* Do some work */ 

    /* Now wake thread B */ 
    pthread_mutex_lock(&run_lock_b); 
    run_thread_b = 1; 
    pthread_cond_signal(&run_cond_b); 
    pthread_mutex_unlock(&run_lock_b); 
} 

/* thread B */ 
while (1) { 
    /* Wait for Thread B to be runnable */ 
    pthread_mutex_lock(&run_lock_b); 
    while (!run_thread_b) 
     pthread_cond_wait(&run_cond_b, &run_lock_b); 
    run_thread_b = 0; 
    pthread_mutex_unlock(&run_lock_b); 

    /* Do some work */ 

    /* Now wake thread A */ 
    pthread_mutex_lock(&run_lock_a); 
    run_thread_a = 1; 
    pthread_cond_signal(&run_cond_a); 
    pthread_mutex_unlock(&run_lock_a); 
} 

प्रत्येक धागा जब तक अन्य धागा संकेत यह जगाने के लिए pthread_cond_wait() अवरोधित कर देगा: आप हालत चर का उपयोग करना चाहिए। यह डेडलॉक नहीं होगा।

इसे int, pthread_cond_t और pthread_mutex_t प्रति थ्रेड आवंटित करके आसानी से कई धागे तक बढ़ाया जा सकता है।

+0

@caf मैंने मूल रूप से किसी शर्त का उपयोग करने की कोशिश की थी, लेकिन मेरे धागे को एक साथ चलने की आवश्यकता है, और जब तक कि मैं प्रत्येक के लिए कोई शर्त नहीं बनाना चाहता (शर्तों की एक सरणी काम नहीं करेगी क्योंकि इसे हर बार अवरुद्ध कर दिया जाएगा जब इसे किसी भी द्वारा एक्सेस किया गया था धागा, इस प्रकार वांछित समरूपता को खत्म कर रहा है) मैं नहीं देखता कि मैं यह काम कैसे कर सकता हूं। – ubiquibacon

+0

@typoknig: शर्तों की एक सरणी बिल्कुल वही है जो आपको चाहिए। इसे हर बार अवरुद्ध नहीं किया जाएगा जब इसे किसी थ्रेड द्वारा एक्सेस किया गया था "। प्रत्येक कंडीशन वैरिएबल स्वतंत्र है - इससे कोई फ़र्क नहीं पड़ता कि आप उन्हें सरणी में रखते हैं या अलग-अलग नामांकित ग्लोबल्स में रखते हैं। – caf

+0

@caf मैंने अपना प्रश्न अपडेट किया है और अपना कोड जोड़ा है, शायद आप इसे देख सकते हैं। मुझे पता है कि आपने जो संरचना सुझाई है वह सही है, लेकिन मैं अभी भी इसे सही काम नहीं कर सकता (अपडेटेड प्रश्न देखें)। मैंने जो कोड पोस्ट किया है, वह पूरी तरह से फिर से लिखा गया है जब मैंने अपने प्रश्न (अब स्थिति का उपयोग कर) पूछा था। – ubiquibacon

18

आप pthread_mutex_trylock का उपयोग कर सकते हैं। यदि यह सफल होता है, तो म्यूटेक्स को दावा नहीं किया गया था और अब आप इसका स्वामी हैं (इसलिए आपको इसे जारी करना चाहिए और अपने मामले में "अनदेखा" वापस करना चाहिए)। अन्यथा, कोई इसे पकड़ रहा है।

मुझे तनाव देना है कि "यह देखने के लिए जांच करें कि क्या एक म्यूटेक्स अनधिकृत है" एक बहुत बुरा विचार है। इस तरह की सोच में निहित दौड़ की स्थिति है। यदि ऐसा फ़ंक्शन आपको t पर बताता है कि लॉक अनदेखा है, तो यह कहता है कि कुछ अन्य थ्रेड ने t+1 पर लॉक हासिल किया है या नहीं।

मामले में यह एक कोड उदाहरण के साथ बेहतर सचित्र है, पर विचार करें:

bool held = is_lock_held(); 

if (!held) 
{ 
    // What exactly can you conclude here? Pretty much nothing. 
    // It was unheld at some point in the past but it might be held 
    // by the time you got to this point, or by the time you do your 
    // next instruction... 
} 
+0

@asveikau रिलीज़ करता है मेरी समस्या यह है कि मेरे पास एक थ्रेड (ए) है जो दूसरे धागे (बी) पर नियंत्रण पास करता है और फिर खुद को ताला लगा देता है। एक बार धागा 'बी' किया जाता है तो यह थ्रेड' ए' को खोल देता है और फिर खुद को ताला लगा देता है। सिस्टम बहुत अच्छा काम करता है लेकिन दुर्लभ अवसर थ्रेड 'बी' थ्रेड 'ए' थ्रेड 'ए' थ्रेड 'ए' लॉक से पहले अनलॉक करता है, इस प्रकार "अनलॉक" खो जाता है और प्रोग्राम मृत ताले होते हैं। मैंने 'trylock' का उपयोग करने की कोशिश की है, लेकिन जिस तरह से आपने सुझाव दिया है ... मैं फिर कोशिश करूंगा। – ubiquibacon

+0

@typoknig - ऐसा लगता है कि आपको एक सरल सिंक्रनाइज़ेशन योजना पर विचार करना चाहिए। उदाहरण के लिए, आप बी सिग्नल एक सेमफोर हो सकता है कि ए इंतजार कर रहा है। – asveikau

+0

@asveikau मुद्दा यह है कि थ्रेड ए के पास नियंत्रण है और उसे खुद को लॉक करना होगा, और मेरा कोई नियंत्रण नहीं है कि यह कितनी तेज़ी से ताला लगाता है। बी थ्रेड ए के लिए सेमफोर को सिग्नल/अनलॉक करता है, जब थ्रेड बी किया जाता है, लेकिन अगर थ्रेड ए ने अभी तक लॉक नहीं किया है (और थ्रेड बी के बाद अनलॉक के लिए संकेत दिया गया है) तो थ्रेड ए लॉक रहेगा। – ubiquibacon

0

आप एक पूर्णांक के साथ एक pthread_mutex_t तुलना नहीं कर सकते।

आपको लगता है कि जाँच करने के लिए

int pthread_mutex_trylock(pthread_mutex_t *mutex);

उपयोग कर सकते हैं।

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