【问题标题】:Is there a built-in semaphore structure that allows for waiting on more than one resource?是否有允许等待多个资源的内置信号量结构?
【发布时间】:2019-04-24 20:26:02
【问题描述】:

我希望一次能够等待/发布多个资源。是否有允许这样做的内置 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);

这将简单地等待直到所有资源都可用,然后在将信号量减少请求的资源数量后返回。我觉得我前一段时间看到过类似的东西,但似乎无法弄清楚。

【问题讨论】:

  • 根据你锁定的频率和时间,你可以使用带有原子变量的spinlock,大概。
  • 这将用作管道的一部分,因此我可能等待的时间没有限制
  • 信号量只是一种协调方式,你也可以使用互斥锁。在任何情况下,您都需要等待所有这些信号量翻转,因此并行等待或串行等待对结果没有任何影响。要么他们都清楚,要么有障碍。
  • “并行等待或串行等待对结果没有变化”,这取决于信号量正在同步的资源类型。出于我的目的,结果会改变,并行等待根本不是一种选择。我需要以连续的方式将资源分配给线程。与其他线程并行等待单个资源将提供位置稀疏的资源。如果没有任何内置的东西很好,我只是想我记得不久前使用过类似的东西,但找不到任何东西,所以我想我会伸手去这里检查一下。
  • 如果它被测序,那就太好了,这会让你的生活更轻松。您只需一个接一个地抓住一个,然后在不再需要它们时释放它们。这个问题最初读到,您需要以任何特定顺序获取 N 个信号量。

标签: c semaphore


【解决方案1】:

您目前正在使用 POSIX 信号量。它们不直接提供以原子方式将信号量值更改超过 1 的可能性,除非在创建新信号量时。

System V 信号量 (semget / semctl / semop) 通常被认为是劣质的,但它们确实具有 POSIX 风格所缺乏的一些特性,这就是其中之一。具体来说,您可以使用semop()原子地从信号量的值中扣除任何正数,直到可以在不将值减小到零以下的情况下进行阻塞。

但总体而言,System V IPC 已经够痛苦了,我建议改为设置一个表示当前可用资源数量的共享变量,并使用互斥锁 + 条件变量而不是信号量。看起来像这样:

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);
    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    相关资源
    最近更新 更多