我工作的一个项目,并试图用pthread_cond_wait()pthread_cond_signal()同步两个线程。

我的代码看起来是这样的:

pthread_mutex_t lock_it = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t write_it = PTHREAD_COND_INITIALIZER;

   int main(int argc, char**argv)
  {

     pthread_t t_send_segments, t_recv_acks;

     pthread_create(&t_send_segments, NULL, send_segments, (void*)NULL);
     pthread_create(&t_recv_acks,     NULL, recv_acks,     (void*)NULL);

     pthread_join(t_recv_acks, (void**)NULL);

     pthread_mutex_destroy(&lock_it);
     pthread_cond_destroy(&write_it);
}

 void* send_segments(void *v) {
    for(;;) {
       pthread_mutex_lock(&lock_it);
       printf("s1\n");
       printf("s2\n");
       pthread_cond_wait(&write_it, &lock_it);
       printf("s3\n");
       printf("s4\n");
       printf("s5\n"); 
       pthread_mutex_unlock(&lock_it);
    }
    return 0;
 }

 void* recv_acks(void *v) {
    for(;;) {
       pthread_mutex_lock(&lock_it);
       printf("r1\n");
       pthread_cond_signal(&write_it);
       printf("r2\n");
       pthread_mutex_unlock(&lock_it);
    }  
    return 0;
 }

预期的输出是:

s1
s2
r1
s3
s4
s5
s1
s2
r2
r1
s3
s4
s5

(etc)

我的输出不遵循此模式在所有。显然,我有一个逻辑错误的地方,但我不理解在哪里。为什么没有recv_acks()线程的总是的,当它击中的pthread_cond_signal()产量 - 因为pthread_cond_wait()总是先执行(因为我在其中创建线程的顺序)和cond_wait()一直以来执行的关键部?

有帮助吗?

解决方案

pthread_cond_signal功能不会引起当前线程,以产生和不释放互斥。它所做的就是重新启动一个线程已经暂停本身通过pthread_cond_wait的条件。这只是意味着唤醒线程可用于调度,它不会导致它立即执行。线程调度器将在未来某个时候调度它。

此外,仅仅因为S-线程已经觉醒,并争夺互斥体,这并不意味着它会得到下一个互斥体。互斥不一定公平已经要求它的所有线程。按照pthread_mutex手册页:“pthread_mutex_lock锁定给出互斥如果互斥锁是目前解锁,就变成由调用线程锁定和拥有,pthread_mutex_lock立即返回。”所以R-线程可以在其多次循环旋转,高高兴兴地解锁并通过调度被交换出去之前重新锁定互斥多次。这意味着S-线程只会在互斥得到一个机会,如果调度发生过程中,它已经发布了互斥的短暂时间中断R-主题。

要实现所需的输出,两个线程将需要控制它们的执行与病症和悬浮剂本身之前信号彼此。然而,这可能是也可能不是你真正想要与你的实际项目做什么。

另注:这其实并不重要,你在创造什么样的顺序线程创建一个线程不会产生创建线程。因此,主线程可能会创建两个线程都被安排之前,线程调度器可以自由地安排执行其中任何一个未来。如果S-还没有登录,您的平台上首次运行,这恰好是你的平台上实施的行为,是不是应该被依靠。

其他提示

我似乎记得读书的地方,pthread_cond_signal()实际上并没有导致线程立即产生。由于pthread_cond_signal()不解除锁定,调用它继续执行,直到它释放锁的线程,并且只的然后的它产生并允许信号线从pthread_cond_wait()返回。

如果是这样的话,那么我认为你的输出看起来像

s1
s2
r1
r2
s3
s4
s5

等....如果不是,你可能需要编辑的实际输出到你的问题得到一个准确的答案。

您是做了错误的使用条件。我不明白你想要什么,但你正在尝试做的看起来很像称为生产者/消费者问题可与条件像我一样后实施一个典型的同步问题。

您应该对此有看就懂的条件是如何使用的。 问题如下: 我有两个线程,一个将数据写入固定大小和从缓冲器另一读取数据的缓冲器。如果缓冲器满了第一线程不能写入更多的数据,如果所述缓冲器是空的第二不能读取。

#include <stdlib.h>
#include <stdio.h>

#include <pthread.h>

#define BUFFER_SIZE 4 

int buffer_nb_entries = 0; 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 

void send(){
for(;;){
  pthread_mutex_lock(&mutex);
  while( buffer_nb_entries == BUFFER_SIZE) /* If buffer is full, then wait */
    pthread_cond_wait(&cond, &mutex); 

  /* Here I am sure that buffer is not full */
  printf("sending\n"); 
  buffer_nb_entries++;

  pthread_cond_signal(&cond); // signal that the condition has changed. 
  pthread_mutex_unlock(&mutex); 
 }
}

void receive(){
  for(;;){
    pthread_mutex_lock(&mutex); 
    while(buffer_nb_entries == 0)
      pthread_cond_wait(&cond, &mutex);
    /* Here I am sure that buffer is not empty */
    printf("receiving\n");
    buffer_nb_entries--; 
    pthread_cond_signal(&cond); 
    pthread_mutex_unlock(&mutex); 
  }

}

int main(){
  pthread_t s, r; 

  pthread_create(&s, NULL, (void *(*)(void*))send, NULL); 
  pthread_create(&r, NULL, (void *(*)(void*))receive, NULL); 

  pthread_join(s, NULL); 

}

请注意,您必须测试的东西调用调用pthread_cond_wait()之前,如果你不这样做,如果你的信号功能被称为前,那么你可能永远睡。

我觉得你的麻烦试图使用一个锁太多的东西进来。您应该只使用一个锁一样东西,这样,没有你在等待什么混乱。我建议增加对写信号的第二锁。此外,你应该添加第二个cond_wait的消息的第二分组。如果不这样做,那东西在运行的顺序是随机的。这里是我的编辑程序的版本:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NUM_MESSAGES 3
int messages = 0;
void * send_segments(void *);
void * recv_acks(void *v);
pthread_mutex_t lock_it = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t write_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t write_cond = PTHREAD_COND_INITIALIZER;

   int main(int argc, char**argv)
  {

     pthread_t t_send_segments, t_recv_acks;

     pthread_create(&t_send_segments, NULL, send_segments, (void*)NULL);
     pthread_create(&t_recv_acks,     NULL, recv_acks,     (void*)NULL);

     pthread_join(t_recv_acks, (void**)NULL);
     pthread_join(t_send_segments, (void**)NULL);

     //pthread_mutex_destroy(&lock_it);
     //pthread_cond_destroy(&write_it);
}

 void* send_segments(void *v) {
    for(;;) {
       pthread_mutex_lock(&lock_it);
       printf("s1\n");
       printf("s2\n");
       pthread_mutex_unlock(&lock_it);

       // wait for other thread
       pthread_mutex_lock(&write_mutex);
       pthread_cond_wait(&write_cond, &write_mutex);
       pthread_mutex_unlock(&write_mutex);

       pthread_mutex_lock(&lock_it);
       printf("s3\n");
       printf("s4\n");
       printf("s5\n"); 
       pthread_mutex_unlock(&lock_it);

       // wait for other thread
       pthread_mutex_lock(&write_mutex);
       pthread_cond_wait(&write_cond, &write_mutex);
       pthread_mutex_unlock(&write_mutex);

       if (messages > NUM_MESSAGES) return( NULL );
    }
    return 0;
 }


 void* recv_acks(void *v) {
    for(;;) {
       // write first response
       pthread_mutex_lock(&lock_it);
       printf("r1\n");
       pthread_mutex_unlock(&lock_it);

       // signal other thread
       pthread_mutex_lock(&write_mutex);
       pthread_cond_signal(&write_cond);
       pthread_mutex_unlock(&write_mutex);

       // write second response
       pthread_mutex_lock(&lock_it);
       printf("r2\n\n");
       // increment count before releasing lock, otherwise the other thread
       // will be stuck waiting for a write_cond signal
       messages++;
       pthread_mutex_unlock(&lock_it);

       // signal other thread
       pthread_mutex_lock(&write_mutex);
       pthread_cond_signal(&write_cond);
       pthread_mutex_unlock(&write_mutex);

       if (messages > NUM_MESSAGES) return(NULL);
    } 
    return 0;
 }

如果我运行此程序时,得到下面的输出(请注意,我添加了第二新行R2后,为了清楚起见):

leif@indurain:~/tmp$ ./test
s1
s2
r1
s3
s4
s5
r2

s1
s2
r1
s3
s4
s5
r2

s1
s2
r1
s3
s4
s5
r2

s1
s2
r1
s3
s4
s5
r2

leif@indurain:~/tmp$ 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top