2012-02-13 54 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_lock()代替pthread_mutex_trylock(),讓你的線程將等待互斥體在爭用時可用。幾乎在所有情況下你都想要的東西是pthread_mutex_lock(); _trylock變體僅用於優化一些不尋常的情況 - 如果您遇到需要_trylock的情況,您將會知道。

+0

出於好奇,你能否提供一個例子,其中'..._ lock()'優於'..._ trylock()'?防爆。如果你想實現一個超時,不會'trylock'成爲選擇嗎?或者超時沒有意義嗎? – theMayer 2018-02-15 22:22:46

+1

'..._lock()'在大多數情況下都是合適的選項,因爲在大多數情況下,線程不能在不使用互斥鎖的情況下做出任何有用的前進進度。在這種情況下,如果使用'... trylock()'並且不能接受鎖定,則唯一的選擇是循環並嘗試再次鎖定它。 只有在需要外部事件的情況下才需要超時,這些外部事件往往會映射到條件變量,因此可以使用'pthread_cond_timedwait()'。對互斥體的無限等待表明代碼本身存在問題,而非異常情況。 – caf 2018-02-19 00:35:47

+0

同意這裏的最後一句話......我有一些遺留代碼,開發人員有點過於雄心勃勃,也許不明白線程是如何工作的。該代碼也試圖一次睡眠一個毫秒的線程。你必須笑,否則它會讓你哭! – theMayer 2018-02-19 01:03:34

0

該代碼旨在阻止以確保互斥您撥打pthread_mutex_trylock()。否則它是未定義的行爲。因此,您必須致電pthread_mutex_lock()

0

用while循環鎖定的修改版本應該更穩定。

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) 
... 

您的代碼是沒有意義的。它在哪裏被鎖定?這就像一個不工作的自旋鎖使用更多的CPU?!

的tryLock返回0時鎖定,所以:

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

如果上 mutex引用的互斥對象鎖定獲取的pthread_mutex_trylock()函數將返回零。否則,將返回一個錯誤 以指示錯誤。

0

pthread_mutex_trylock的使用用於確保tou不會導致競爭特定命令。 爲了做到這一點,您必須使用pthread_mutex_trylock作爲條件!一個不假設它會自行工作。 example- while(pthread_mutex_trylock(& my_mutex)== 0){ printf(「互斥量在我的控制下!\ n「); }

這樣你可以肯定的是,即使互斥已被鎖定,你正在做在特定線程abusy,等待它

3

咖啡館就如何偉大的答案我只需要自己解釋一下這個解釋,但是我確實知道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; 
} 

顯然你會評論一名工作人員來測試它,但如果你嘗試一下,我得到Time Spent: 1.36200作爲pthread_mutex_lock()Time Spent: 0.36714pthread_mutex_trylock()的平均值。

如果您使用Atomics,速度會更快。

+0

這個答案值得投票。對於某些情況,您需要使用_trylock,但請確保您檢查結果的結果。 – 2017-07-16 17:22:17

+0

我想知道在這種情況下自旋鎖是否會成爲性能提升的原因?請參閱https://stackoverflow.com/questions/6603404/when-is-pthread-spin-lock-the-right-thing-to-use-over-e-g-a-pthread-mutex – theMayer 2018-02-15 22:29:25