c - 条件变量的实现

标签 c linux multithreading gcc pthreads

为了理解pthread条件变量的代码,我写了自己的版本。它看起来正确吗?我在一个程序中使用它,它可以工作,但工作速度出奇地快。最初该程序大约需要 2.5 秒,而使用我的条件变量版本只需 0.8 秒,程序的输出也是正确的。但是,我不确定我的实现是否正确。

struct cond_node_t
{
    sem_t s;
    cond_node_t * next;
};

struct cond_t
{
    cond_node_t * q;                // Linked List
    pthread_mutex_t qm;                 // Lock for the Linked List
};

int my_pthread_cond_init( cond_t * cond )
{
    cond->q = NULL;
    pthread_mutex_init( &(cond->qm), NULL );
}

int my_pthread_cond_wait( cond_t* cond, pthread_mutex_t* mutex )
{
    cond_node_t * self;

    pthread_mutex_lock(&(cond->qm));
    self = (cond_node_t*)calloc( 1, sizeof(cond_node_t) );
    self->next = cond->q;
    cond->q = self;
    sem_init( &self->s, 0, 0 );
    pthread_mutex_unlock(&(cond->qm));

    pthread_mutex_unlock(mutex);
    sem_wait( &self->s );
    free( self ); // Free the node
    pthread_mutex_lock(mutex);
}

int my_pthread_cond_signal( cond_t * cond )
{
    pthread_mutex_lock(&(cond->qm));
    if (cond->q != NULL) 
    {
        sem_post(&(cond->q->s));
        cond->q = cond->q->next;
    }
    pthread_mutex_unlock(&(cond->qm));
}

int my_pthread_cond_broadcast( cond_t * cond )
{
    pthread_mutex_lock(&(cond->qm));
    while ( cond->q != NULL) 
    {
        sem_post( &(cond->q->s) );
        cond->q = cond->q->next;
    }
    pthread_mutex_unlock(&(cond->qm));
}

最佳答案

除了缺少返回值检查之外,还有一些应该可以修复的问题:

  • sem_destroy 未被调用。
  • 信号/广播在唤醒目标线程后触及 cond_node_t,可能导致释放后使用。

进一步评论:

  • 省略的销毁操作可能需要更改其他操作,因此当 POSIX 表示它应该安全时销毁条件变量是安全的。不支持 destroy 或对其调用时间施加更严格的限制将使事情变得简单。
  • 生产实现将处理线程取消。
  • 退出等待(例如线程取消和 pthread_cond_timedwait 超时所需)可能会导致并发症。
  • 您的实现在用户空间中对线程进行排队,这是出于性能原因在某些生产实现中完成的;我不明白为什么。
  • 您的实现始终按 LIFO 顺序对线程进行排队。这通常更快(例如因为缓存效应)但可能导致饥饿。生产实现有时可能会使用 FIFO 顺序以避免饥饿。

关于c - 条件变量的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11000725/

相关文章:

c - skb校验和计算功能可能导致系统挂起

c++ - 如何设置c控制台窗口标题

在 Linux 上动态链接到 libc 时调用 `atexit`

c - Linux - c - 没有上下文切换和低开销的 ipc 通知?

linux - Linux服务故障转移的解决方案

c++ - 是否可以在 OpenSUSE 上降级 glibc?

java - 如果发生异常则退出 Java Callable

java - 在事件调度线程中显示 JWindow

c++ - C/C++ 为什么对二进制数据使用 unsigned char?

multithreading - 连通分量的并行算法