Как использовать 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);
}

и затем main ():

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 каждая вещь отображается очень последовательно!

что за нелепая ошибка здесь?

6 ответов


звонить не имеет смысла 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 необходимо, вы узнаете.


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

ваш код не имеет смысла. Где она заперта силой? Это как не работающий spinlock, который использует больше CPU?!

trylock возвращает 0, когда он блокируется, так что:

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

функция pthread_mutex_trylock() возвращает ноль, если блокировка включена объект мьютекса, на который ссылается мьютекс, приобретается. В противном случае ошибка номер возвращается для указания ошибки.


у 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;   
}

очевидно, вы прокомментируете одного работника, чтобы проверить его, но если вы попробуете, я получу Time Spent: 1.36200 в среднем для pthread_mutex_lock() и Time Spent: 0.36714 на pthread_mutex_trylock().

снова ускоряется, если вы используете атомную технику.


код предназначен для блокировки, чтобы обеспечить взаимоисключение где вы называете pthread_mutex_trylock(). В противном случае это неопределенное поведение. Поэтому вы должны позвать pthread_mutex_lock().


модифицированная версия force locked with while loop должна быть более стабильной.

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

}`


использование pthread_mutex_trylock используется, чтобы гарантировать, что tou не вызовет гонку к определенной команде. Для этого вы должны использовать pthread_mutex_trylock в качестве условия! не предполагайте, что он будет работать самостоятельно. образец- while (pthread_mutex_trylock(&my_mutex)==0){ printf ("мьютекс находится под моим контролем!!\северный"); }

таким образом, вы можете быть уверены, что даже если мьютекс теперь заблокирован, Вы делаете abusy-ожидание его в этом конкретном потоке.