TL; DR
我有一个家庭作业,需要实现线程同步。在实现过程中,我担心pthread_cond_wait()是否也会在伪启动时(而不是成功唤醒时)锁定互斥体。
任务
该任务是一个工作人员/交货问题,其中存在为工作人员提供订单的工作人员线程和管理线程。为此,有一个订单 list , worker 可以从中获取订单,管理线程可以下达订单。订单列表是共享对象,需要同步。
到目前为止我的解决方案
我认为,对于这个问题,我需要一个列表监控器,以保护列表免受空虚的访问或列表满时的存款的侵害。

void deposit_order(order_list* ol, order* o){
    pthread_mutex_lock(&(ol->mut_order_access));
    while(get_count(ol) >= MAX_ORDERS) {
        pthread_cond_wait(&(ol->cond_not_full), &(ol->mut_order_access));
    }

    ol->orders[ol->head] = o;
    ol->head = (ol->head+1)%MAX_ORDERS;
    ol->count++;

    pthread_cond_signal(&(ol->cond_not_empty));
    pthread_mutex_unlock(&(ol->mut_order_access));
}

order* get_order(order_list* ol) {
    pthread_mutex_lock(&(ol->mut_order_access));
    while(get_count(ol) <= 0) {
        pthread_cond_wait(&(ol->cond_not_empty), &(ol->mut_order_access));
    }
    order* o;

    o = ol->orders[ol->tail];
    ol->tail = (ol->tail+1)%MAX_ORDERS;
    ol->count--;

    pthread_cond_signal(&(ol->cond_not_full));
    pthread_mutex_unlock(&(ol->mut_order_access));
    return o;
}
我认为结构包含的内容并不重要,因为主题是如何同步访问。显然,结构order_list包含一个mutex和两个条件变量以向另一个线程发出信号。因此,如果工作人员从列表中删除任务,它会向管理线程发出“不为空”的信号,以便它可以下达其他订单。如果管理人员将订单下达信号通知工作线程“不为空”,则一个线程可以从列表中删除订单。
我的关注
到目前为止,还算不错,但现在我认为,有一种情况可能是上述解决方案很关键的事件,这是“虚假的唤醒”。从this thread中,我了解到,如果相应的互斥锁mut_order_access被另一个线程锁定,则线程无法伪造的唤醒。但是,例如,如果列表中仅存在一个顺序,从而无法满足get_count(ol) >= MAX_ORDERS,并且线程从等待中虚假地唤醒,检查条件并将其标记为不正确,然后跳出循环,该怎么办?然后,另一个线程接收到该信号,并在前一个线程已进入关键区域后正常唤醒,从而锁定互斥锁。因此,现在两个线程都将处于关键区域,这将是一个失败。
问题
因此,仅当线程在虚假唤醒时未锁定互斥锁时,上述情况才会发生,因此是否在虚假唤醒时锁定互斥锁?

最佳答案

您对虚假唤醒条件的理解似乎不正确。伪唤醒与互斥锁是否被另一个线程锁定无关。除非您遇到编程错误(破坏这些函数的约定,一般的内存损坏或其他未定义的行为等),否则在没有由调用线程保持(锁定)互斥锁的情况下,pthread_cond_wait永远不会返回。如果发生虚假唤醒,则直到重新获取互斥体后,它仍然无法返回。即使在使用pthread_cancel取消了服务员的情况下,取消清理处理程序也无法开始运行,直到重新获取互斥体为止。

关于c - pthread_cond_wait是否锁定互斥和虚假唤醒,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56707687/

10-12 14:30