Как читать/записывать общую переменную с помощью pthreads?
Вопрос
У меня есть два потока, использующие C pthreads в Linux.Один из них записывает данные, а другой их читает.Я использую переменную, чтобы разрешить поток чтения, когда разрешено чтение, и поток записи, когда разрешено.Таким образом, мьютекс применяется к этой логической переменной с именем «newData».Мой вопрос:нужно ли мне блокировать/разблокировать мьютекс вокруг доступа внутри условия «if»?Оба способа работают, но я думаю, просто потому, что вероятность перекрытия записи/чтения этой переменной очень мала.Я показываю обе альтернативы, чтобы лучше объяснить мой вопрос:
Тема 1:
pthread_mutex_lock( &lattice_mutex );
if (!newData) {
pthread_mutex_unlock( &lattice_mutex );
uchar *lattice_pos = lattice;
int i;
for(i=0; i<size; i++) {
*lattice_pos = rand()%CHAR_MAX;
lattice_pos++;
}
pthread_mutex_lock( &lattice_mutex );
newData = TRUE;
pthread_mutex_unlock( &lattice_mutex );
} else {
pthread_mutex_unlock( &lattice_mutex );
}
Тема 2:
pthread_mutex_lock( &lattice_mutex );
if(newData) {
pthread_mutex_unlock( &lattice_mutex );
renderUpdate();
pthread_mutex_lock( &lattice_mutex );
newData = FALSE;
pthread_mutex_unlock( &lattice_mutex );
} else {
pthread_mutex_unlock( &lattice_mutex );
}
Вторая версия, которая работает, но я не знаю, правильна ли она:
Тема 1:
if (!newData) {
uchar *lattice_pos = lattice;
int i;
for(i=0; i<size; i++) {
*lattice_pos = rand()%CHAR_MAX;
lattice_pos++;
}
pthread_mutex_lock( &lattice_mutex );
newData = TRUE;
pthread_mutex_unlock( &lattice_mutex );
}
Тема 2:
if(newData) {
renderUpdate();
pthread_mutex_lock( &lattice_mutex );
newData = FALSE;
pthread_mutex_unlock( &lattice_mutex );
}
Решение
Это производно от вашей первой версии - она несколько проще.
Тема 1:писатель
pthread_mutex_lock(&lattice_mutex);
if (!newData) {
pthread_mutex_unlock(&lattice_mutex); // Omit?
uchar *lattice_pos = lattice;
int i;
for (i = 0; i < size; i++)
*lattice_pos++ = rand() % CHAR_MAX;
pthread_mutex_lock(&lattice_mutex); // Omit?
newData = TRUE;
}
pthread_mutex_unlock(&lattice_mutex);
Тема 2:читатель
pthread_mutex_lock(&lattice_mutex);
if (newData) {
pthread_mutex_unlock(&lattice_mutex); // Omit?
renderUpdate();
pthread_mutex_lock(&lattice_mutex); // Omit?
newData = FALSE;
}
pthread_mutex_unlock(&lattice_mutex);
Это зависит от того, как именно информация о решетке предназначена для использования, но, учитывая название Mutex, я думаю, что вы должны держать ее заблокированным, когда вы модифицируете решетку, отсюда две пары строк, отмеченные «пропуск?» следует удалить.В противном случае решетка не защищена от одновременного доступа.
Добавлен:Думаю вторая версия ошибочна - она плохо защищает решетку.
Другие советы
Первая версия верна: вам нужен мьютекс как для записи, так и для чтения.
Однако, AFAIK, почти все архитектуры имеют простой доступ для чтения и записи к одной единице данных (например.int) атомный.Однако обратите внимание, что на архитектурах со слабым упорядочением памяти могут возникнуть проблемы, например, когда флаг «buffer-full» станет истинным до того, как буфер фактически будет содержать данные.
Обратите внимание, что этот код, вероятно, не самое лучшее, что вы можете сделать, поскольку он никогда не переходит в режим ожидания (использует ожидание занятости).Если вы хотите дождаться данных в любом из потоков, вам придется использовать условную переменную с мьютексом.