2012-02-13 12 views
6

का उपयोग trylock:pthread_mutex_trylock का उपयोग कैसे करें?

FILE   *fp; 
pthread_mutex_t demoMutex; 

void * printHello (void* threadId) 
{ 
    pthread_mutex_trylock (&demoMutex); 

    pthread_t  writeToFile = pthread_self(); 
    unsigned short iterate; 
    for (iterate = 0; iterate < 10000; iterate++) 
    { 
     fprintf (fp, " %d ", iterate,   4); 
     fprintf (fp, " %lu ", writeToFile, sizeof (pthread_t)); 
     fprintf (fp, "\n",  writeToFile, 1); 
    } 

    pthread_mutex_unlock (&demoMutex); 
    pthread_exit (NULL); 
} 

और फिर मुख्य():

int main() 
{ 
    pthread_t  arrayOfThreadId [5]; 
    int     returnValue; 
    unsigned int iterate; 

    fp = fopen ("xyz", "w"); 
    pthread_mutex_init (&demoMutex, NULL); 

    for (iterate = 0; iterate < 5; iterate++) 
    { 
     if (returnValue = pthread_create (&arrayOfThreadId [iterate], 
            NULL, 
            printHello, 
            (void*) &arrayOfThreadId [iterate]) != 0) 
     { 
      printf ("\nerror: pthread_create failed with error number %d", returnValue); 
     } 
    } 

    for (iterate = 0; iterate < 5; iterate++) 
     pthread_join (arrayOfThreadId [iterate], NULL); 

    return 0; 
} 

यहाँ उत्पादन पहले पहले धागा और फिर बाकी के कुछ उसके बाद फिर से पहले प्रिंट, और। लॉक काम नहीं कर रहा है। यदि मैं इसे pthread_mutex_lock के साथ प्रतिस्थापित करता हूं तो हर चीज बहुत अनुक्रमिक रूप से दिखाई देती है!

हास्यास्पद गलती क्या है?

उत्तर

21

परिणाम की जांच किए बिना pthread_mutex_trylock() पर कॉल करना समझ में नहीं आता है।

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

void *printHello(void *threadId) 
{ 
    if (pthread_mutex_trylock(&demoMutex) == 0) 
    { 
     unsigned short iterate; 
     for (iterate = 0; iterate < 10000; iterate++) 
     { 
      fprintf (fp, " %d\n", iterate); 
     } 

     pthread_mutex_unlock (&demoMutex); 
    } 

    pthread_exit (NULL); 
} 

हालांकि, यह शायद, और अधिक समझ में आता है pthread_mutex_trylock() के बजाय pthread_mutex_lock() का उपयोग करें ताकि आपके थ्रेड म्यूटेक्स उपलब्ध होने पर प्रतीक्षा करने के लिए इंतजार करेंगे। pthread_mutex_lock() लगभग सभी मामलों में है जो आप चाहते हैं; _trylock संस्करण केवल कुछ असामान्य मामलों को अनुकूलित करने के लिए है - यदि आपको कभी ऐसी स्थिति का सामना करना पड़ता है जहां _trylock आवश्यक है, तो आपको पता चलेगा।

+0

जिज्ञासा से, क्या आप एक उदाहरण प्रदान कर सकते हैं जहां '..._ lock()' को '..._ trylock()' को प्राथमिकता दी जाती है? पूर्व। यदि आप एक टाइमआउट को कार्यान्वित करना चाहते हैं, तो 'trylock' पसंद नहीं होगा? या क्या यह एक टाइमआउट करने के लिए समझ में नहीं आता है? – theMayer

+1

'..._ लॉक()' ज्यादातर मामलों में उपयुक्त विकल्प है क्योंकि ज्यादातर मामलों में, थ्रेड म्यूटेक्स लेने के बिना कोई उपयोगी आगे प्रगति नहीं कर सकता है। इस मामले में, यदि '' trylock() 'का उपयोग किया जाता है और लॉक नहीं ले सकता है, तो एकमात्र विकल्प चारों ओर लूप करना है और इसे फिर से लॉक करने का प्रयास करना है। टाइमआउट केवल उन मामलों में आवश्यक होना चाहिए जहां आगे की प्रगति के लिए बाहरी घटना की आवश्यकता होती है, जो एक शर्त चर के लिए मानचित्रण करता है और इसलिए 'pthread_cond_timedwait() 'का उपयोग किया जा सकता है। एक म्यूटेक्स पर एक असीमित प्रतीक्षा एक असाधारण स्थिति के बजाय कोड में एक समस्या को इंगित करता है। – caf

+0

अंतिम वाक्य के साथ सहमत हैं ... मुझे कुछ विरासत कोड मिला है जहां डेवलपर को थोड़ा महत्वाकांक्षी मिला है और शायद यह समझ में नहीं आया कि थ्रेडिंग कैसे काम करती है। कोड एक समय में एक मिलीसेकंद के लिए धागे को सोने का प्रयास कर रहा है। आपको हंसना है, अन्यथा यह आपको रोता है! – theMayer

0

कोड पारस्परिक बहिष्करण सुनिश्चित करने के लिए ब्लॉक करने के लिए है, जहां आप pthread_mutex_trylock() पर कॉल करते हैं। अन्यथा यह अपरिभाषित व्यवहार है। इससे पहले कि आपको pthread_mutex_lock() पर कॉल करना होगा।

0

लूप को एक स्थिर संस्करण के साथ लॉक किया गया है जबकि लूप अधिक स्थिर होना चाहिए।

void *printHello(void *threadId) 

{ 

    while (pthread_mutex_trylock(&demoMutex) == 0) 

    { 

     unsigned short iterate; 

     for (iterate = 0; iterate < 10000; iterate++) 

     { 

      fprintf (fp, " %d\n", iterate); 

     } 


     pthread_mutex_unlock (&demoMutex); 

     break; 

    } 

pthread_exit (NULL); 

} `

4
... 
while (pthread_mutex_trylock(&demoMutex) == 0) 
... 

आपका कोड कोई मतलब नहीं है। यह बल कहाँ बंद है? यह एक काम नहीं कर रहे स्पिनलॉक की तरह है जो अधिक सीपीयू का उपयोग करता है ?!

trylock रिटर्न 0 जब यह ताले, तो:

if(!pthread_mutex_trylock(&demoMutex)) 
{ 
    // mutex locked 
} 

pthread_mutex_trylock() फ़ंक्शन शून्य लौटा देगा अगर म्युटेक्स वस्तु म्युटेक्स द्वारा संदर्भित पर एक ताला हासिल कर ली है। अन्यथा, त्रुटि इंगित करने के लिए त्रुटि संख्या लौटा दी गई है।

0

pthread_mutex_trylock का उपयोग यह सुनिश्चित करने के लिए किया जाता है कि टूर किसी विशिष्ट कमांड की दौड़ का कारण नहीं बनता है। ऐसा करने के लिए, आपको एक शर्त के रूप में pthread_mutex_trylock का उपयोग करना होगा! ऐसा नहीं लगता कि यह स्वयं द्वारा काम करेगा। उदाहरण- जबकि (pthread_mutex_trylock (& my_mutex) == 0) { printf ("mutex मेरे नियंत्रण में है !!\ N ");। }

कि जिस तरह से आप यह सुनिश्चित करें कि भले ही म्युटेक्स अब लॉक होता है, आप उस विशेष धागे में इसके लिए abusy-इंतज़ार कर कर रहे हैं हो सकता है

3

CAF पर कैसे एक महान जवाब था इसका उपयोग करने के लिए। मुझे बस अपने लिए उस स्पष्टीकरण को पकड़ना पड़ा, हालांकि मैंने सीख लिया कि pthread_mutex_lock() कक्षा में कहीं अधिक ओवरहेड है और <time.h> lib का उपयोग करके इसे अभी परीक्षण किया गया है और मेरे लूप के प्रदर्शन में काफी वृद्धि हुई है। बस उन दो में जोड़ना सेंट्स ने उल्लेख किया है कि शायद आपको pthread_mutex_lock() का उपयोग करना चाहिए!

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#define NUM_THREADS 4 
#define LOOPS 100000 

int counter; 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

// using pthread_mutex_lock 
void* worker() { 
    for (int i = 0; i < LOOPS; i++) { 
     pthread_mutex_lock(&mutex); 
     counter++; 
     pthread_mutex_unlock(&mutex); 
    } 
    pthread_exit(NULL); 
} 

// using try_lock - obviously only use one at a time 
void* worker() { 
    for (int i = 0; i < LOOPS; i++) { 
     while (pthread_mutex_trylock(&mutex) != 0) { 
      // wait - treated as spin lock in this example 
     } 

     counter++; 
     pthread_mutex_unlock(&mutex); 
    } 
    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) { 
    clock_t begin = clock(); 
    pthread_t t[NUM_THREADS]; 
    int rc; 

    counter = 0; 

    for (int i = 0; i < NUM_THREADS; i++) { 
     rc = pthread_create(&t[i], NULL, worker, NULL); 

     if (rc) { 
      printf("Thread #%d failed\n", i); 
     } 
    } 

    for (int i = 0; i < NUM_THREADS; i++) { 
     pthread_join(t[i], NULL); 
    } 

    printf("%d\n", counter); 
    clock_t end = clock(); 
    double time = (double)(end - begin)/CLOCKS_PER_SEC; 

    printf("Time Spent: %f", time); 

    return 0; 
} 

जाहिर है आप एक कार्यकर्ता को इसका परीक्षण करने के लिए टिप्पणी करेंगे, लेकिन यदि आप इसे आज़माते हैं, तो pthread_mutex_lock() और Time Spent: 0.36714 के लिए pthread_mutex_trylock() के लिए औसत के रूप में Time Spent: 1.36200 प्राप्त होता है।

यदि आप परमाणुओं का उपयोग करते हैं तो तेज़ी से आगे बढ़ता है।

+0

यह उत्तर एक अप वोट के लायक है। कुछ स्थितियों के लिए, आपको _ ट्रायलॉक का उपयोग करने की आवश्यकता है, लेकिन सुनिश्चित करें कि आप परिणाम के परिणाम परिणाम की जांच करें। –

+0

मुझे आश्चर्य है कि इस मामले में स्पिन लॉक आपके प्रदर्शन में वृद्धि का कारण हो सकता है? Https://stackoverflow.com/questions/6603404/when-is-pthread-spin-lock-the-right-thing-to-use-over-e-g-a-pthread-mutex देखें – theMayer

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