繁体   English   中英

两个线程从相同的 function RT Linux 给出不同的 output

[英]Two threads giving different output from same function RT Linux

我有 2 个线程和一个 function,我从两个线程调用相同的 function“no_elements()”,function 是

int front = -1, rear = -1;
int no_elements()
{

int q_size = 0;

if (front == 0)
{
    
    q_size = rear + 1;

    return q_size;
}
else if (front != 0 && rear != 0)
{
    
    q_size = (rear - front) + 1;
    return q_size;
}
else if (rear == 0 && front != 0)
{
    
    q_size = (SIZE - front)+1;
    return q_size;
}
else if (rear == -1 || front == -1 )
    {
        q_size = 0;
        printf("empty---- ---------------------------------------------------------------------");
        return q_size;
    }

}

并且两个线程调用相同的 function

iret1 = pthread_create(&thread1, NULL, producer,(void*) message1);
iret2 = pthread_create(&thread2, NULL, consumer,(void*) message2);

生产者和消费者函数是

void *producer(void *ptr) // enque function
{
char *message;
printf("%s \n", message);
enQueue(data);
printf("No of elements%d\n",no_elements());
}

第二个 function 是

void *consumer(void *ptr) // enque function
{
char *message;
printf("%s \n", message);
printf("No of elements%d\n",no_elements());
}

并入队 function 是

void enQueue(double *element)
{

 if (isFull())
 printf("\n Queue is full!! \n");
 else
 {

     int i=0;
    if (front == -1)
{
    front = 0;
}
rear = (rear + 1) % SIZE;

memcpy(items[rear].value, element, sizeof (items[rear].value)); // better: sizeof struct

printf("front is  %d--",front);
printf("rear is  %d\n",rear);


 }
}

但是第一个线程给出了正确的结果,第二个给出了前后的初始化值。

这里前面和后面是全局变量,它们在第一个线程中由入队 function 操作,然后我调用 function no_elements() 返回一个正确的值。

但同时第二个线程返回了前后端的初始化值

有什么问题?

可以这样做吗?

   void enQueue(double *element)
   {
    pthread_mutex_lock(&lock);

   if (isFull())
    printf("\n Queue is full!! \n");
    else
   {

   int i=0;
   if (front == -1)
   {
  front = 0;
  }
  rear = (rear + 1) % SIZE;

 memcpy(items[rear].value, element, sizeof (items[rear].value)); // better: 
 sizeof struct

printf("front is  %d--",front);
printf("rear is  %d\n",rear);


 }
 pthread_mutex_unlock(&lock);
}

从同时处于活动状态的多个线程调用no_elements() function 和/或enqueue() function 会产生多个数据竞争,因此程序的行为是未定义的。 考虑到某些访问是写入,数据竞争源于那些访问共享变量frontrearitems (至少)而没有任何同步的函数。 您必须保护共享变量免受并发访问,通常通过创建每个线程在访问这些变量之前必须成功锁定的互斥锁。 线程还必须确保在访问后的某个时间点解锁互斥锁,以便为其他线程提供锁定它的机会。

访问 object 而另一个线程正在或可能正在访问它的结果是未定义的。 你在frontread都有这个问题。 因此,您的程序的结果是未定义的,并且可能完全无法预测。

程序员有责任确保线程不会同时访问同一个 object。 为此目的有很多工具,而enQueue的第一个版本没有使用它们。

当您调用 pthread_create 时,接下来实际执行的内容是不确定的。 pthread_create手册页:

除非采用实时调度策略,否则在调用 pthread_create() 之后,不确定哪个线程(调用者或新线程)接下来将执行。

如果将其扩展到创建两个线程的场景,则执行顺序更加不确定。 换句话说,您无法知道生产者消费者将首先开始执行。

您可以通过像这样重写 pthread 代码来解决此问题:

iret1 = pthread_create(&thread1, NULL, producer,(void*) message1);
pthread_join(&thread1, NULL);
iret2 = pthread_create(&thread2, NULL, consumer,(void*) message2);
pthread_join(&thread2, NULL);

编辑:附加说明 - 如果您需要同时创建和运行线程,那么您可以使用信号量等机制在生产者线程之前延迟消费者线程。 我认为互斥锁虽然在保护变量的完整性方面绝对正确,但仍不能保证线程执行的顺序。 唯一的另一种方法是为任务分配优先级..

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM