Как использовать 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-ожидание его в этом конкретном потоке.