Как я могу собрать LOCK_EX, если всегда есть LOCK_SH?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как я могу собрать LOCK_EX, если всегда есть LOCK_SH?

Сообщение Anonymous »

У меня многопоточное приложение.
Один из потоков — это поток фонового обслуживания, которому требуется монопольный доступ к некоторым файлам. В остальное время файл может читаться (и читается) несколькими потоками.
И чтение, и обслуживание занимают некоторое время, примерно 1 секунду.
Я ожидал, что смогу использовать стадо для файла; эксклюзивная блокирующая группа для потока обслуживания и блокирующая общая группа для потоков чтения.
К сожалению, если файл имеет общую группу, новая общая группа имеет приоритет над эксклюзивной группой (предположительно, поскольку она может быть выдана немедленно).
Существует так много перекрывающихся читателей, что всегда есть хотя бы один читатель.
Есть ли способ заблокировать новые общие группы, пока ожидается эксклюзивная группа?
Моей первой мыслью было использовать вторую группу (всегда эксклюзивную, заблокированную, если какой-либо поток ожидает группы), чтобы заставить первые группы выполняться последовательно. Поскольку стаи основаны на файлах, только для этого потребуется второй файл. Кажется, это слишком накладно.
Есть ли лучший способ?
Вот код, демонстрирующий эту проблему:

Код: Выделить всё

/*
* if VERBOSE is defined, the shared threads will
* list every flock & unflock.
*/

#define VERBOSE

#include 
#include 
#include 
#include 
#include

void exclusive_flock() {
int fd = open("flockfile", O_RDWR | O_CREAT | O_TRUNC);

printf("Waiting on exclusive flock\n");
flock(fd, LOCK_EX);
printf("Lock successfull!\n");

flock(fd, LOCK_UN);
printf("Unlocked\n");
close(fd);
}

void *shared_thread_routine(void *threadnum_data) {
int *pthreadnum = (int *)threadnum_data;
int threadnum = *pthreadnum;
printf("thread %d starting to juggle shared flocks\n", threadnum);
// these threads get shared flocks for a while then
// release them.
// Since they are shared, they get issued immediately
// (unless an exclusive flock succeeds).
// they overlap, so there is never a time when none
// of the threads have a shared flock.
for (int i = 0; i < 30; i++) {
int fd = open("flockfile", O_RDWR | O_CREAT | O_TRUNC);
// open a shared flock
flock(fd, LOCK_SH);

#ifdef VERBOSE
printf("thread %d has a shared flock on fd %d\n", threadnum, fd);
#endif

// read the file, do some work
sleep(1);

// release the flock; hopefully give exclusive_thread a chance:
flock(fd, LOCK_UN);
close(fd);

#ifdef VERBOSE
printf("thread %d has released it's flock on fd %d\n", threadnum, fd);
#endif

// a short delay between runs
usleep(4000 * (threadnum) );
}
printf("thread %d done\n", threadnum);
}

int main (int argc, char *argv[]) {
pthread_t threads[10];
for (int threadnum = 0; threadnum < 10; threadnum ++) {
pthread_create(&threads[threadnum],
NULL, shared_thread_routine, &threadnum);
usleep(1000);
}
exclusive_flock();
for (int threadnum = 0; threadnum < 10; threadnum ++) {
pthread_join(threads[threadnum],NULL);
}
}

Чего я хочу: пока не будет запрошена эксклюзивная группа, все общие группы будут выданы немедленно.
Как только будет запрошена эксклюзивная блокировка, новые общие группы не будут разрешены (поскольку они ждут за эксклюзивной группой), пока эксклюзивная группа не будет выпущена.
Как я могу это сделать?
Я думаю, что приведенный выше пример является кроссплатформенным, но я использую gcc на Linux. Мой код должен работать только под Linux.
Большинство онлайн-компиляторов C не будут запускать этот код, поскольку он создает файлы.
Он работает на https://www.jdoodle.com/c-online-compiler

Подробнее здесь: https://stackoverflow.com/questions/798 ... -a-lock-sh
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»