web-dev-qa-db-ja.com

pthread_mutex_trylockの使用方法は?

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に置き換えると、すべてが非常に順番に表示されます。

ここでばかげた間違いは何ですか?

9
Aquarius_Girl

結果をテストせずにpthread_mutex_trylock()を呼び出すことは意味がありません。

ミューテックスの取得に失敗した場合は、notクリティカルセクションに入り、後でロックを解除する必要がありますnot。たとえば、次のように書き直すことができます(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_が必要な状況に遭遇した場合は、ご存知でしょう。

28
caf
...
while (pthread_mutex_trylock(&demoMutex) == 0)
...

あなたのコードは意味がありません。強制ロックはどこにありますか?より多くのCPUを使用するスピンロックが機能していないようなものですか?!

trylockロックすると0を返すため、次のようになります。

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

Pthread_mutex_trylock()関数は、ミューテックスによって参照されるミューテックスオブジェクトのロックが取得された場合、ゼロを返します。それ以外の場合は、エラーを示すエラー番号が返されます。

6
Gesior.pl

cafはそれを使用する方法について素晴らしい答えを持っていました。私は自分でその説明をつかむ必要がありましたが、pthread_mutex_lock()はクラスではるかにオーバーヘッドがあり、_<time.h>_ libを使用してテストしただけで、ループのパフォーマンスが大幅に向上しました。 。代わりにpthread_mutex_lock()を使用する必要があると彼が言ったので、その2セントを追加するだけです。

_#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;   
}
_

明らかに、1人のワーカーをコメントアウトしてテストしますが、試してみると、pthread_mutex_lock()の平均として_Time Spent: 1.36200_が、pthread_mutex_trylock()の平均として_Time Spent: 0.36714_が得られます。 。

Atomicsを使用すると、再び高速になります。

4
Dennis O'Keeffe

whileループでロックされたforceの修正バージョンは、より安定しているはずです。

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

} `

0
lyxmoo

このコードは、pthread_mutex_trylock()を呼び出す場所相互排除を確実にするためにブロックすることを目的としています。それ以外の場合は、未定義の動作です。したがって、pthread_mutex_lock()を呼び出す必要があります。

0
yves Baumes

Pthread_mutex_trylockを使用して、touが特定のコマンドとの競合を引き起こさないようにします。そのためには、条件としてpthread_mutex_trylockを使用する必要があります。それがそれ自体で機能するとは限りません。例-while(pthread_mutex_trylock(&my_mutex)== 0){printf( "ミューテックスは私の制御下にあります!!\n"); }

そうすれば、ミューテックスがロックされている場合でも、その特定のスレッドでミューテックスを待機していることを確認できます。

0
Ron Cohen