[英]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.