我正在实现pthread条件变量(基于linuxfutexs),我有一个想法可以避免进程共享条件变量对pthread_cond_broadcast
的“踩踏效应”。对于非进程共享cond var s,futex requeue操作传统上(即NPTL)用于将服务员从cond var的futex重新排队到互斥体的futex,而不唤醒他们,但对于进程共享cond vars,这通常是不可能的,因为pthread_cond_broadcast
可能没有指向关联互斥体的有效指针。在最坏的情况下,互斥锁甚至可能无法映射到其内存空间中。
我解决这个问题的想法是让pthread_cond_broadcast
只直接唤醒一个服务生,并让该服务生在唤醒时执行重新队列操作,因为它确实有指向互斥锁的所需指针。
如果我采用这种方法,自然会有很多丑陋的竞争条件需要考虑,但是如果这些条件可以克服,是否还有其他原因会导致这种实现无效或不受欢迎?我能想到的一个可能无法克服的问题是,负责重新排队的服务生(一个单独的进程)在重新排队开始之前就被杀死了,但通过将condvar futex放在健壮的互斥列表中,以便内核在进程结束时对其执行唤醒,甚至可以克服这个问题。
最佳答案
可能有属于多个地址空间的等待者,每个地址空间在内存中的不同地址映射了与futex关联的互斥体。我不确定当所有服务生的重新排队点可能没有映射到同一个地址时,FUTEX_REQUEUE
是否可以安全使用;如果映射到了,那么这就不是问题了。
还有其他一些问题是健壮的futex无法检测到的;例如,如果您选择的服务生在信号处理程序中很忙,您可能会等待任意长的时间。[如评论中所述,这些不是问题]
注意,对于健壮的futex,必须将futex& 0x3FFFFFFF
的值设置为要唤醒的线程的TID;如果要唤醒,还必须将bitFUTEX_WAITERS
设置为on。这意味着您必须选择从广播线程中唤醒哪个线程,否则您将无法在FUTEX_WAKE
之后立即处理线程死亡。您还需要处理线程在waker线程将其TID写入状态变量之前立即死亡的可能性—也许在健壮的互斥系统中注册一个“pending master”字段也是一个好主意。
我看不出这为什么不能工作,那么,只要你一定要处理线程退出问题仔细。也就是说,最好在内核中简单地定义一个FUTEX_WAIT
的扩展,它接受一个重新队列点和比较值作为参数,并让内核以一种简单的、无种族歧视的方式处理这个问题。
关于c - 条件变量的延迟bcast唤醒-是否有效?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7536401/