Mutex занимает много времени, чтобы разблокировать - PullRequest
4 голосов
/ 19 мая 2010

У меня есть две темы. Первый примерно такой:

while(1)
{
   pthread_mutex_lock(&mutex);
   //DO WORK
   pthread_mutex_unlock(&mutex);
   pthread_yield();
}

Второй блокирует мьютекс по событию пользователя, изменяет некоторые настройки и разблокирует. Поток один делает ~ 200 итераций в секунду. Однако в некоторых случаях второй поток занимает до 3 секунд, чтобы стать активным (чтобы заблокировать мьютекс). Как обеспечить более быстрый ответ?

РЕДАКТИРОВАТЬ- вторая нить:

while(1)
{
   waitForUserInput(); // blocking call to linux input
   pthread_mutex_lock(&mutex);
   // Change some settings which are used by the first thread
   pthread_mutex_unlock(&mutex);
}

EDIT2 - Исправлен вопрос («разблокировать мьютекс» -> «заблокировать мьютекс»).

Ответы [ 3 ]

1 голос
/ 20 мая 2010

Попробуйте изменить pthread_yield() на usleep(10) или usleep(100), чтобы определить, вызывает ли доход проблемы у вас, как я видел случаи, когда доходность ничего не делает, что может привести к тому, что ваш цикл будет разблокирован и слишком быстро первый поток, чтобы поймать свою блокировку большую часть времени. Тогда вы можете рассмотреть возможность просмотра условных переменных в pthread, если вам нужен больший контроль.

1 голос
/ 27 октября 2011

Ваш дизайн плохой. Поток должен содержать мьютекс только тогда, когда ему необходим доступ к разделяемым структурам данных. Это должна быть небольшая часть времени выполнения потока, а не подавляющее большинство его. Если вы видите модель, которую вы разрабатываете, пришло время изменить дизайн.

Один из возможных шаблонов состоит в том, чтобы вычислительный поток удерживал указатель на глобальные данные, пока он работает без удержания мьютекса. Поток пользовательского интерфейса может затем создать новую версию глобальных данных на основе ввода пользовательского интерфейса, а затем опубликовать указатель на новые данные, чтобы вычислительный поток увидел их при следующем получении указателя. Таким образом, вычислительный поток должен удерживать мьютекс только столько времени, сколько потребуется для копирования указателя.

Вот упрощенная схема для вычислительной нити:

pthread_mutex_lock(&mutex);
my_pointer = shared_pointer;
pthread_mutex_unlock(&mutex);
do_calculations();

А для потока пользовательского интерфейса логика выглядит следующим образом: вы изменяете копию данных. Вы делаете новую копию данных. Вы приобретаете мьютекс. Вы изменяете shared_pointer, указывая на одну из двух копий данных. Вы удерживаете другую копию для изменения на следующем проходе.

1 голос
/ 19 мая 2010

Меня всегда беспокоит, когда я вижу pthread_yield, это нестандартно в соответствии с справочной страницей , поэтому я вообще избегаю этого, и в любом случае это действительно не дает никаких гарантий, оно поставит вас в в конце очереди выполнения, но это не означает, что все остальное будет работать в зависимости от того, как ОС установит приоритет для вашего потока.

вы можете явно передать управление другому потоку, используя условные переменные signal и wait

...