[英]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 会产生多个数据竞争,因此程序的行为是未定义的。 考虑到某些访问是写入,数据竞争源于那些访问共享变量front
、 rear
和items
(至少)而没有任何同步的函数。 您必须保护共享变量免受并发访问,通常通过创建每个线程在访问这些变量之前必须成功锁定的互斥锁。 线程还必须确保在访问后的某个时间点解锁互斥锁,以便为其他线程提供锁定它的机会。
访问 object 而另一个线程正在或可能正在访问它的结果是未定义的。 你在front
和read
都有这个问题。 因此,您的程序的结果是未定义的,并且可能完全无法预测。
程序员有责任确保线程不会同时访问同一个 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.