Существует ли встроенная структура семафора, которая позволяет ожидать более одного ресурса? - PullRequest
0 голосов
/ 24 апреля 2019

Я хотел бы иметь возможность ждать / публиковать более одного ресурса одновременно. Есть ли встроенная структура c и интерфейс, который учитывает это?

В настоящее время я использую semaphore.h, однако этот интерфейс имеет ограничение, заключающееся в том, что он может запрашивать только один ресурс за раз.

Я мог бы сделать что-то вроде этого:

for (int i = 0; i < resources; i++)
    sem_wait(my_sem);

Но это заняло бы много времени, если resources велико, и мне также нужно было бы добавить еще одну блокировку перед этим, чтобы я гарантировал, что запрашивающая сторона имеет приоритет над другими потоками, которые могут запрашивать ресурсы. В конечном итоге это будет выглядеть примерно так:

sem_wait(my_lock);
for (int i = 0; i < resources; i++)
    sem_wait(my_sem);
sem_post(my_lock);

не говоря уже о дополнительных проверках ошибок, которые должны были бы произойти.

То, что я хотел бы сделать, это что-то вроде этого:

sem_wait(my_lock, resources);

Это просто подождет, пока все ресурсы не станут доступны, а затем вернется после уменьшения семафора на запрошенное количество ресурсов. Я чувствую, что видел что-то подобное некоторое время назад, но не могу понять это.

1 Ответ

1 голос
/ 24 апреля 2019

В настоящее время вы используете семафоры POSIX.Они напрямую не предоставляют возможность атомарного изменения значения семафора более чем на единицу, кроме случаев создания нового семафора.

Семафоры System V (semget / semctl / semop) обычно рассматриваютсяуступает, но у них есть некоторые особенности, которых нет у POSIX, и это одна из них.В частности, вы можете использовать от semop() до атомарно вычитать любое положительное число из значения семафора, блокируя до тех пор, пока это не будет сделано без уменьшения значения ниже нуля.

Но System V IPC достаточноВ целом, я бы посоветовал вместо этого установить общую переменную, представляющую количество доступных в настоящее время ресурсов, и использовать переменную условия mutex + вместо семафора.Это будет выглядеть примерно так:

unsigned resources_available = ALL_RESOURCES;
pthread_mutex_t resource_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t resource_cv = PTHREAD_COND_INITIALIZER;

// ...

int acquire_resources(unsigned resources_wanted) {
    int result;

    // ...

    result = pthread_mutex_lock(resource_mutex);
    // handle errors ...
    while (resources_available < resources_wanted) {
        result = pthread_cond_wait(resource_cv, resource_mutex);
        // handle errors ...
    }
    resources_available -= resources_wanted;
    result = pthread_mutex_unlock(resource_mutex);
    // ...
}

int release_resources(unsigned resources_released) {
    int result;

    // ...

    result = pthread_mutex_lock(resource_mutex);
    // handle errors ...
    resources_available += resources_released;
    result = pthread_cond_broadcast(resource_cv);
    // handle errors ...
    result = pthread_mutex_unlock(resource_mutex);
    // ...
}
...