C 条件变量和互斥锁解锁

C 条件变量和互斥锁解锁,c,pthreads,mutex,condition-variable,C,Pthreads,Mutex,Condition Variable,代码: void*inc_func(void*arg) { pthread_mutex_lock(&mutex); pthread_cond_信号(&count_threshold_cv); 睡眠(1); pthread_mutex_unlock(&mutex); } void*watch(void*arg) { pthread_mutex_lock(&mutex); pthread_cond_wait(&count_threshold_cv,&mutex); 睡眠(1); pthread_mu

代码:

void*inc_func(void*arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_信号(&count_threshold_cv);
睡眠(1);
pthread_mutex_unlock(&mutex);
}
void*watch(void*arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&count_threshold_cv,&mutex);
睡眠(1);
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t id[2];
pthread_创建(&id[0],NULL,watch,NULL);
pthread_create(&id[1],NULL,inc_func,NULL);
int i;
对于(i=0;i
  • pthread\u mutex\u lock()

  • pthread\u cond\u wait()
    在开始等待时解锁互斥体,并在返回前锁定。如果相关互斥体仍处于锁定状态,则返回可能会延迟。然后返回将延迟,直到互斥体解锁

将以上内容放在一起并将其应用到您展示的代码中,您会看到每个线程函数都以锁定和解锁(等等)开始,所以一切都很好

参考示例代码:
pthread\u cond\u wait()
在调用
pthread\u mutex\u unlock()
时返回


若要成功处理示例代码描述的场景,需要考虑两个特殊情况

  • 信号先发后发的情况
  • 所谓的情况,即
    pthread\u cond\u wait()
    在未发出信号的情况下返回
  • 为了处理这两种情况,每个条件都应该有一个watch变量

    void *inc_func(void *arg)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_signal(&count_threshold_cv);
        sleep(1);
        pthread_mutex_unlock(&mutex);
    }
    void *watch(void *arg)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&count_threshold_cv,&mutex);
        sleep(1);
        pthread_mutex_unlock(&mutex);
    }
    int main()
    {
        pthread_t id[2];
        pthread_create(&id[0],NULL,watch,NULL);
        pthread_create(&id[1],NULL,inc_func,NULL);
        int i;
        for(i=0;i<2;i++)
            pthread_join(id[i],NULL);
    }
    
    pthread\u mutex\u t mutex=。。。
    pthread_cond_t count_threshold_cv=。。。
    int信号=0;
    void*inc_func(void*arg)
    {
    pthread_mutex_lock(&mutex);
    pthread_cond_信号(&count_threshold_cv);
    信号=1;
    pthread_mutex_unlock(&mutex);
    }
    void*watch(void*arg)
    {
    pthread_mutex_lock(&mutex);
    而(0==信号)
    {
    pthread_cond_wait(&count_threshold_cv,&mutex);
    }
    pthread_mutex_unlock(&mutex);
    }
    内部主(空)
    {
    pthread_t id[2];
    pthread_创建(&id[0],NULL,watch,NULL);
    pthread_create(&id[1],NULL,inc_func,NULL);
    int i;
    
    对于(i=0;i

    • watch
      首先运行并锁定(而
      inc_func
      等待)
    • watch
      使用
      pthread\u cond\u wait
      打开互斥文本并根据
    这些函数以原子方式释放互斥,并导致调用线程 在条件变量cond上阻塞

    这允许以下操作

    • inc_func
      获取互斥锁,然后发出信号(此时互斥锁尚未释放)
    • inc_func
      释放互斥锁
    • 由于已释放互斥锁且互斥锁已解锁,
      watch
      的执行将按照以下步骤继续锁定互斥锁:
    成功返回后,互斥锁已被锁定,并由调用线程拥有

    • 接下来是互斥的合法释放

    您没有考虑的情况是,如果代码< CixFunc < /C> >代码首先执行而不切换到<代码> WHOR> <代码> < /P>

    • inc_func
      锁定互斥锁
    • inc_func
      发出信号,但没有人需要发出信号,这是正常的
    • inc_func
      解锁互斥锁
    • 监视
      锁定互斥锁
    • 然后等待条件变量,但没有人发出信号,因此它将永远等待

    这个问题可能是重复的。在展示一些示例代码时已经回答了这个问题,这肯定会有助于避免误解您。我对这个问题进行了更好的重新表述think@InQusitive:您错误地假设
    pthread\u cond\u wait()
    由于
    pthread\u cond\u signal()而返回
    已被调用。情况并非如此。每个定义不能有两个线程持有相同的互斥体。这就是它们的用途。
    pthread\u mutex\u lock()
    如果在已锁定的互斥锁上调用,将只阻塞,而不会返回@InQusitive@InQusitive:您的真实代码是否初始化了它使用的互斥体?您的真实代码是否检查每个
    pthread_*()
    调用函数,测试它是否可能失败?是的,无论如何,我对互斥条件的理解是错误的。现在很清楚了。:)请在答案中添加第二条注释。
    pthread_mutex_t mutex = ...
    pthread_cond_t count_threshold_cv = ...
    
    int signalled = 0;
    
    void *inc_func(void *arg)   
    {
      pthread_mutex_lock(&mutex);
    
      pthread_cond_signal(&count_threshold_cv);
      signalled = 1;
    
      pthread_mutex_unlock(&mutex);  
    }
    
    void *watch(void *arg)
    {
      pthread_mutex_lock(&mutex);
    
      while (0 == signalled)
      {
        pthread_cond_wait(&count_threshold_cv,&mutex);
      }
    
      pthread_mutex_unlock(&mutex);
    }
    
    int main(void)
    {
      pthread_t id[2];
      pthread_create(&id[0],NULL,watch,NULL);
      pthread_create(&id[1],NULL,inc_func,NULL);
      int i;
      for(i=0;i<2;i++)
        pthread_join(id[i],NULL);
    }