簡體   English   中英

多線程程序中的錯誤

[英]Bug in multithreaded program

我必須制作一個具有共享變量(初始值為35的計數器)和5個線程的程序。 我必須編寫程序,以便每個線程訪問計數器的值並將其減1。這應該繼續進行直到計數器= 0。

到目前為止,這就是我的代碼,但是問題是只有一個線程將counter的值減為0。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>

#define NTHREADS 5
void *thread_function1(void *);
void *thread_function2(void *);
void *thread_function3(void *);
void *thread_function4(void *);
void *thread_function5(void *);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
short int  counter = 35;


main()
{
   pthread_t thread_id[NTHREADS];
   pthread_t thread1, thread2, thread3, thread4, thread5;
int status, status2, status3, status4, status5;

status = pthread_create(&thread1, NULL, thread_function1, NULL);
if(status!=0){
    fprintf(stderr,"thread 1 failed\n");    
}

status2 = pthread_create(&thread2, NULL, thread_function2, NULL);
if(status2!=0){
    fprintf(stderr,"thread 2 failed\n");    
}

status3 = pthread_create(&thread3, NULL, thread_function3, NULL);
if(status3!=0){
    fprintf(stderr,"thread 3 failed\n");    
}

status4 = pthread_create(&thread4, NULL, thread_function4, NULL);
if(status4!=0){
    printf("thread 4 failed\n");    
}

status5 = pthread_create(&thread5, NULL, thread_function5, NULL);
if(status5!=0){
    fprintf(stderr,"thread 5 failed\n");    
}

//pthread_join(thread1, NULL);
//int x = counter;

printf("created all the threads \n");

printf("joining thread 1");
    pthread_join(thread1, NULL);
printf("joining thread 2");
    pthread_join(thread2, NULL);
printf("joining thread 3");
    pthread_join(thread3, NULL);
printf("joining thread 4");
    pthread_join(thread4, NULL);
printf("joining thread 5");
    pthread_join(thread5, NULL);                          

   printf("Final counter value: %d\n", counter);
}

void *thread_function1(void *dummyPtr)
{
   printf("Thread number %ld\n", pthread_self());   

while(counter>0){
   srand(time(NULL));

   int r = rand()%3;
  printf(" %d\n", r);
   pthread_mutex_lock( &mutex1 );
  printf("entered the mutex");
   counter--;
   printf(" %d\n", counter);
   sleep(r);
   pthread_mutex_unlock( &mutex1 );
   printf("mutex unlocked");
   pthread_yield();
}

}

void *thread_function2(void *dummyPtr)
{
   printf("Thread number %ld\n", pthread_self());   

while(counter>0){
   srand(time(NULL));

   int r = rand()%3;
  printf(" %d\n", r);
   pthread_mutex_lock( &mutex1 );
  printf("entered the mutex");
   counter--;
   printf(" %d\n", counter);
   sleep(r);
   pthread_mutex_unlock( &mutex1 );
   pthread_yield();
}

}

void *thread_function3(void *dummyPtr)
{
   printf("Thread number %ld\n", pthread_self());   

while(counter>0){
   srand(time(NULL));
   int r = rand()%3;
  printf(" %d\n", r);
   pthread_mutex_lock( &mutex1 );
  printf("entered the mutex");
   counter--;
   printf(" %d\n", counter);
   sleep(r);
   pthread_mutex_unlock( &mutex1 );
   pthread_yield();
}

}

void *thread_function4(void *dummyPtr)
{
   printf("Thread number %ld\n", pthread_self());   

while(counter>0){
   srand(time(NULL));

   int r = rand()%3;
  printf(" %d\n", r);
   pthread_mutex_lock( &mutex1 );
  printf("entered the mutex");
   counter--;
   printf(" %d\n", counter);
   sleep(r);
   pthread_mutex_unlock( &mutex1 );
   pthread_yield();
}

}

void *thread_function5(void *dummyPtr)
{
   printf("Thread number %ld\n", pthread_self());   

while(counter>0){
   srand(time(NULL));

   int r = rand()%3;
   printf(" %d\n", r);
   pthread_mutex_lock( &mutex1 );
   printf("entered the mutex");
   counter--;
   printf(" %d\n", counter);
   sleep(r);
   pthread_mutex_unlock( &mutex1 );
   pthread_yield();
}

}

誰能幫忙嗎? 謝謝

int r = rand()%3;
/* ... */
sleep(rand);

r是介於0到2之間的隨機數,但是您需要睡眠rand秒,這是一個函數的地址,該地址將隱式轉換為無符號int-因此線程將在很長一段時間內處於睡眠狀態。 使用sleep(r); 代替。

另外,請注意,您在不持有互斥量的情況下讀取了counter (在while(counter > 0) ),這可能導致程序無法正常工作,具體取決於體系結構,緩存和編譯器優化。 您應該鎖定互斥鎖,將counter的值讀取到局部變量,然后解鎖互斥鎖並檢查該值是否為正。

盡管安蒂找到了一個不錯的選擇,但我還有其他幾點要發表:

  • 您不需要五個相同的功能。 您只能擁有一個功能,並以不同的線程啟動它五次。

  • 您正在鎖定互斥鎖的狀態下睡覺。 這意味着在一個線程休眠時其他線程將阻塞。 我認為您想在釋放鎖定后進入睡眠狀態,以便其他線程可以在櫃台使用。

  • 當您在while循環條件下檢查計數器時,您正在讀取互斥保護之外的計數器。 訪問共享資源時,無論您正在讀取還是寫入,都需要鎖定互斥鎖。 如果您不這樣做,那么您將擁有比賽條件。

  • 如果遵循我的建議並在釋放互斥鎖之后移動睡眠,則無需調用pthread_yield,因為睡眠也會產生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM