C条件变量中的posix线程

时间:2013-04-12 22:34:39

标签: c variables pthreads conditional-statements

我已经完成了对条件变量的阅读,我只是无法理解如何使用它们。

我有一棵树,截至目前,当您为已经存在的节点插入时,它返回0,这意味着它已经存在,因此失败。

我现在想扩展pthreads支持,而不是提及它不能完成,因为它已经存在并返回0,我希望它在一个等待队列,并且一旦删除了请求的节点,继续现在插入

例如,

假设一棵树有3个节点,值为1,5,10 如果我想插入一个值为10的新节点,而不是返回0并抛出该值已经存在的错误,它应该等待值为10的节点删除,一旦删除,它应该返回并且插入

我的插入函数else块,在先前检查过该节点存在该值后返回0,可以放心,知道它存在的逻辑工作正常,现在我只是想添加条件变量支持等待的地方。数据域条件在插入的第一行初始化,因此也完成了。我现在希望当它进入这个块时,cond_wait是将要执行的唯一代码行,然后它将等待删除信号。我的方法在这里吗?如果是,在删除中,我该如何发出信号?请帮帮我,我花了几个小时阅读并查看试图解决这个问题的例子。

代码,

  else

      {
        //IF DUPLICATE EXISTS
        pthread_mutex_lock(&m);
        node->counter++;
        pthread_cond_wait(&node->condition, &m);
        _insert(string, strlen, ip4_address, node, NULL, NULL);
        pthread_mutex_unlock(&m);

        return 1;//I CHANGED IT FROM 0 to one, since if signalled, and if reached to this limit
        //it was probably successful

    }

2 个答案:

答案 0 :(得分:1)

条件变量wait必须包含在循环中。循环的保护测试由互斥锁保护的共享数据的条件。使用条件变量是没有意义的。

如果在插入之前等待删除值为10的节点是有意义的,那么就可以使用如下逻辑:

lock(mutex)
while (tree.contains(key))
  wait(cond, mutex)
tree.insert(key, value)
unlock(mutex)

另一项任务是这样做的:

lock(mutex)
tree.delete(key)
unlock(mutex)
broadcast(cond) // could be in the mutex, but better outside!

当C. A. R. Hoare发明监视器和条件变量时,原始概念略有不同。关于多处理器效率的担忧并不是一个问题,因此支持以下逻辑:

enter(monitor);
if (tree.contains(key))   // no loop
  wait(cond, monitor)
tree.insert(key, value)
leave(monitor);

可以保证当其他任务发出信号时,等待任务将原子地转移回监视器,而其他任务都无法占用监视器。因此,例如当任务在监视器中并删除节点10并发出条件变量信号时,等待该条件变量的第一个任务将保证立即获得监视器。这与POSIX互斥和条件不同(出于好的理由)。

互斥锁和监视器之间的另一个区别是线程不必保持互斥锁来发信号通知条件变量。事实上,不要这样做是个好主意。发信号通知条件变量可能是一项昂贵的操作(内核之旅)。互斥锁应该保护尽可能短的关键区域(理想情况下只需几条指令),以尽量减少争用。

另一个区别是POSIX条件具有pthread_cond_broadcast函数,该函数唤醒等待条件的所有线程。这始终是默认使用的正确函数。在显而易见(或可以证明)唤醒单个线程的情况下,可以使用函数pthread_cond_signal来优化代码。

答案 1 :(得分:1)

以下是假设:

struct tree
{
   ... // some other data (whatever)
   pthread_mutex_t mitex;
   pthread_cond_t  cond;
};

辅助功能:

int tree_contains_value(struct tree *t, int value)
{
    return ...; // returns 0 or 1
}

这是一个插入内容:

void tree_insert(struct tree *t, int val)
{
    pthread_mutex_lock(&t->mutex);
    while (tree_contains_value(t, value))
    {
        pthread_cond_wait(&t->cond, &t->mutex);
    }
    ... // do actual insert
    pthread_mutex_unlock(&t->mutex);
}

并删除:

void tree_remove(struct tree *t, int val)
{
    pthread_mutex_lock(&t->mutex);
    ... //remove value
    pthread_cond_broadcast(&t->cond); // notify all wating threads if any
    pthread_mutex_unlock(&t->mutex);
}