【发布时间】:2019-06-21 16:59:13
【问题描述】:
TL;DR
我有一个作业需要实现线程同步。在实施过程中,我担心pthread_cond_wait() 是否在虚假唤醒时也会锁定互斥锁,而不仅仅是在成功唤醒时。
任务
该任务是一个工人/交付问题,其中存在为工人提供订单的工作线程和管理线程。为此,有一个订单列表,工人从中获取订单,管理线程存放订单。订单列表是共享对象,需要同步。
到目前为止我的解决方案
我认为对于这个问题,我需要一个列表的监视器,以保护它免受空的访问或满时的存款。
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 未完成,并且线程虚假地从等待中唤醒,检查条件并将其标记为不正确并跳出循环,该怎么办。然后另一个线程接收到信号并在前一个线程已经在临界区之后正常唤醒锁定互斥锁。所以现在两个线程都在关键区域,这将是一个失败。
问题
所以只有当线程在虚假唤醒时没有锁定互斥锁时才会发生上述情况,那么它是否在虚假唤醒时锁定互斥锁?
【问题讨论】:
标签: c multithreading pthreads