Как разделить ресурс между двумя группами потоков
Есть 2 группы потоков. В каждой группе по несколько потоков. Есть общий ресурс. Например какая - нибудь коллекция. Нужно, чтобы, когда хотя бы один поток из первой группы успел занять этот ресурс, все остальный из этой же группы могли к ней обращаться. И когда из первой группы перестали обращаться к ресурсу, то вторая будет имеет возможность ею владеть. Нужно, чтобы все это работало без каких - либо "менеджеров". Чисто, чтобы потоки как - то "договорились" между собой.
Ответы (1 шт):
Например, если упростить инициализацию, можно как-то так:
typedef int id_t;
typedef struct glock_t_ {
pthread_mutex_t mtx; // Синхронизация доступа к структуре
id_t owner; // В случае owner_cnt > 0 - id владеющей группы
size_t owner_cnt; // Число текущих владельцев блокировки
pthread_cond_t wait; // Очередь ожидания блокировки
size_t wait_cnt; // Длина очереди ожидания
} glock_t;
#define GLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, -1, 0, \
PTHREAD_COND_INITIALIZER, 0 }
void glock_lock(glock_t *lck, id_t id) {
pthread_mutex_lock(&lck->mtx);
lck->wait_cnt++;
while (id != lck->owner && 0 < lck->owner_cnt) {
pthread_cond_wait(&lck->wait, &lck->mtx);
}
lck->wait_cnt--;
lck->owner = id;
lck->owner_cnt++;
pthread_mutex_unlock(&lck->mtx);
}
void glock_unlock(glock_t *lck) {
pthread_mutex_lock(&lck->mtx);
assert(0 < lck->owner_cnt);
lck->owner_cnt--;
if (0 == lck->owner_cnt && 0 < lck->wait_cnt) {
pthread_cond_broadcast(&lck->wait);
}
pthread_mutex_unlock(&lck->mtx);
}
P.S.
В принципе, корректно обрабатывается любое число групп (различных id). Но для числа групп большего 2, с точки зрения эффективности, желательна переработка очереди ожидания.
Так же, можно обеспечить лучший "быстрый путь" и, при необходимости, решение проблемы "инверсии приоритета".