簡體   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