0

我正在实现 pthread 条件变量(基于 Linux futexes),并且我有一个想法来避免pthread_cond_broadcast进程共享条件变量的“踩踏效应”。对于非进程共享的 cond var,futex 重新排队操作传统上(即通过 NPTL)用于将等待者从 cond var 的 futex 重新排队到 mutex 的 futex 而不唤醒它们,但这对于进程共享的 cond var 通常是不可能的,因为pthread_cond_broadcast可能没有指向关联互斥体的有效指针。在最坏的情况下,互斥锁甚至可能不会映射到其内存空间中。

我克服这个问题的想法是pthread_cond_broadcast只直接唤醒一个服务员,并让该服务员在唤醒时执行重新排队操作,因为它确实具有指向互斥锁的所需指针。

如果我采用这种方法,自然有很多丑陋的竞争条件需要考虑,但是如果可以克服它们,是否还有其他原因导致这种实现无效或不受欢迎?我能想到的一个可能无法克服的潜在问题是负责重新排队的服务员(一个单独的进程)在它可以采取行动之前被杀死的竞争,但是通过放置 condvar 甚至可以克服这个问题futex 在健壮的互斥列表中,以便内核在进程死亡时对其执行唤醒。

4

2 回答 2

2

可能有属于多个地址空间的服务员,每个服务员都将与 futex 关联的互斥锁映射到内存中的不同地址。FUTEX_REQUEUE当重新排队点可能未在所有服务员中映射到同一地址时,我不确定是否可以安全使用;如果确实如此,那么这不是问题。

还有其他一些问题是健壮的 futex 无法检测到的;例如,如果您选择的服务员正忙于信号处理程序,您可能会等待任意长的时间。[正如评论中所讨论的,这些不是问题]

请注意,使用健壮的 futex,您必须将 futex 的值设置& 0x3FFFFFFF为要唤醒的线程的 TID;如果你想唤醒,你还必须设置位FUTEX_WAITERS。这意味着您必须从广播线程中选择唤醒哪个线程,否则您将无法在FUTEX_WAKE. 您还需要处理线程在唤醒线程将其 TID 写入状态变量之前立即死亡的可能性——也许在健壮的互斥体系统中注册一个“待处理的主”字段是个好主意。

我看不出为什么这不能工作,那么,只要你确保仔细处理线程退出问题。也就是说,最好在内核中简单地定义一个以FUTEX_WAIT重新排队点和比较值作为参数的扩展,并让内核以简单、无竞争的方式处理它。

于 2011-09-24T03:38:55.017 回答
0

我只是不明白为什么您认为可能不知道相应的互斥锁。明确说明

未定义对同一条件变量的并发 pthread_cond_timedwait() 或 pthread_cond_wait() 操作使用多个互斥锁的效果;也就是说,当线程等待条件变量时,条件变量将绑定到唯一的互斥体,并且此(动态)绑定将在等待返回时结束。

因此,即使对于进程共享互斥锁和条件,这也必须成立,并且任何用户空间进程必须始终映射与条件关联的相同且唯一的互斥锁。

我不支持允许用户同时将不同的互斥锁关联到一个条件。

于 2011-09-24T07:55:59.153 回答