Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用pthreads的多线程代码中的计数器值意外更改_C_Multithreading_Thread Safety_Pthreads - Fatal编程技术网

C 使用pthreads的多线程代码中的计数器值意外更改

C 使用pthreads的多线程代码中的计数器值意外更改,c,multithreading,thread-safety,pthreads,C,Multithreading,Thread Safety,Pthreads,我正在实现一个完整的动态接收器读取器程序:我有许多接收器线程(由用户决定),每个线程连接到一个特定的客户机,然后一个读取线程按时间顺序从接收器的输出队列中读取数据,并在.log文件中打印数据 所以我连接了一个客户端,创建了第一个接收方线程。我无法理解为什么在读取元素后的读取线程中,第二个接收器(尚未创建)的计数器在没有任何此类指令的情况下突然增加1。以下是涉及的代码部分: 接收器线程: printf("Receiver ID: %d, counter: %d\n", rec_arg->re

我正在实现一个完整的动态接收器读取器程序:我有许多接收器线程(由用户决定),每个线程连接到一个特定的客户机,然后一个读取线程按时间顺序从接收器的输出队列中读取数据,并在.log文件中打印数据

所以我连接了一个客户端,创建了第一个接收方线程。我无法理解为什么在读取元素后的读取线程中,第二个接收器(尚未创建)的计数器在没有任何此类指令的情况下突然增加1。以下是涉及的代码部分:

接收器线程:

printf("Receiver ID: %d, counter: %d\n", rec_arg->receiver_ID, *(rec_arg->counter));
rec_arg->joint_queue[*(rec_arg->tail)] = rec_meas;

pthread_mutex_lock(rec_arg->mtx);
*(rec_arg->tail) = (*(rec_arg->tail) + 1) % QUEUE_SIZE;
(*(rec_arg->counter))++;
pthread_mutex_unlock(rec_arg->mtx);
printf("Receiver ID: %d, counter: %d\n", rec_arg->receiver_ID, *(rec_arg->counter));
printf("Receiver: tail: %d, joint_queue: %p\n", *(rec_arg->tail), (void*) rec_arg->joint_queue);
pthread_cond_signal(rec_arg->notEmpty); 
阅读线索:

  pthread_mutex_lock(read_arg->queue_mtx[i]);
  (*(read_arg->counters[i]))--;
  printf("Reading Thread: counter[%d]: %d\n", i, *(read_arg->counters[i]));

  if( writetofile(filename, &read_meas) == 0)
       fprintf(stderr,"Reading Thread: writetofile() failed\n");

  *(read_arg->OkRead[i]) = 0;
  *(read_arg->OkRead[(i+1) % read_arg->n_joints]) = 1;
  pthread_mutex_unlock(read_arg->queue_mtx[i]);
  printf("Reading Thread: OkRead[%d]: %d\n", (i+1) % read_arg->n_joints, *(read_arg->OkRead[(i+1) % read_arg->n_joints]));

  printf("Reading Thread: counter[%d]: %d\n", (i+1) % read_arg->n_joints, *(read_arg->counters[(i+1) % read_arg->n_joints])); 
输出结果显示:

Reading Thread: counter[0]: 0  
Reading Thread: OkRead[1]: 1  
Reading Thread: counter[1]: 1  
Reading Thread: counter[1]: 1  
更准确地说,可以创建两个线程,当第一个客户端连接时,它发送数据。接收方线程将数据放入其队列中,读取线程将数据保存在.log文件中,递减计数器[0],将读取权限授予第二个接收方(
OkRead[1]=1
),然后,在没有任何关于计数器[1]的说明的情况下,
计数器[1]=1
显示一个增量:
计数器[1]=1

希望问题能被理解,谢谢您的关注

在读取线程中,您是互斥锁外部的队列计数器。 这意味着另一个线程可以同时修改
OkRead[]
计数器[]
。这是一个很好的例子

读取值后,将调用移动到
pthread\u mutex\u unlock()

  printf("Reading Thread: OkRead[%d]: %d\n", (i+1) % read_arg->n_joints, *(read_arg->OkRead[(i+1) % read_arg->n_joints]));

  printf("Reading Thread: counter[%d]: %d\n", (i+1) % read_arg->n_joints, *(read_arg->counters[(i+1) % read_arg->n_joints]));

  pthread_mutex_unlock(read_arg->queue_mtx[i]);
或者在释放互斥锁之前使用存储值的线程局部变量。比如,

  ...
  int joints = (i+1) % read_arg->n_joints;
  int okread = *(read_arg->OkRead[(i+1) % read_arg->n_joints]);
  int counters = *(read_arg->counters[(i+1) % read_arg->n_joints]);

  pthread_mutex_unlock(read_arg->queue_mtx[i]);

  printf("Reading Thread: OkRead[%d]: %d\n", joints, okread);   
  printf("Reading Thread: counter[%d]: %d\n", (i+1) % read_arg->n_joints, counters ); 

我想出来了。多个线程需要访问的每个参数都必须声明为main()中指针的指针,初始化函数需要其地址

以前,我的代码是这样的:

main():

无效信息初始(整数**信息,整数n元素):

无效信息初始(内部***信息,内部n节点):

*info=malloc(n_接头*sizeof(int*);
如果(*info==NULL)
printf(“队列初始化:malloc失败,错误号:%d,意思是:%s\n”,错误号,strerror(错误号));
int i;

对于(i=0;in .b.),并非所有的竞赛条件都是未定义的行为。在这种错误中,C和C++标准中使用的正式术语是数据竞赛,它总是不确定的行为。这与维基百科称之为“非关键竞赛条件”的情况相反,这是不可预知的(但不是未定义的)。行为。@JonathanWakely感谢您的澄清。数据竞赛是这里实际发生的事情。我已经更新了措辞并更改了链接(这不是更好的权威,但描述正确)。我刚刚编辑了提及数据竞赛的内容,它是UB:)我尝试了两种建议,但它仍然显示了其他线程无法访问的未经检查的价值增量。@nikfio也许,您在其他地方也可以进行类似的无保护访问。在发布的代码中我看不到任何其他问题。张贴一封电子邮件。
  int *counter;
  info_init(&counter, n_elem);

  read_arg->counters = &counter;
  *info = malloc(n_joints*sizeof(int*));
  if(*info == NULL) 
  printf("queues_init: malloc failed, errno: %d, meaning: %s\n", errno, strerror(errno));

 int i;
 for(i=0; i<n_joints; i++) {
 info[i] = (int*) malloc(sizeof(int));
  *(info[i]) = 0;
 }

 return;
 }
 int **counter;
 info_init(&counter, n_elem);

 read_arg->counters = counter; 
 *info = malloc(n_joints*sizeof(int*));
 if(*info == NULL) 
 printf("queues_init: malloc failed, errno: %d, meaning: %s\n", errno, strerror(errno));

 int i;
 for(i=0; i<n_joints; i++) {
 (*info)[i] = (int*) malloc(sizeof(int));
 *(*info)[i] = 0;
 }

 return;
 }