多线程程序中的错误

时间:2011-10-16 06:41:11

标签: c ubuntu

我必须创建一个具有共享变量(初始值为35的计数器)和5个线程的程序。我必须创建程序,以便每个线程访问计数器的值并将其递减1.这应该继续,直到counter = 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();
}

}

有人可以帮忙吗? 感谢

2 个答案:

答案 0 :(得分:2)

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

r是0到2之间的随机数,但是你睡眠rand秒,这是一个函数的地址,它将被隐式地转换为unsigned int - 所以线程将会睡眠很长一段时间请改用sleep(r);

另请注意,您在未持有互斥锁(counter)的情况下阅读while(counter > 0),这可能会导致程序无法正常工作,具体取决于体系结构,缓存和编译器优化。您应该锁定互斥锁,将counter的值读取到局部变量,然后解锁互斥锁并检查该值是否为正。

答案 1 :(得分:1)

虽然Antti找到了一个好的,但我还有一些意见要做:

  • 您不需要五个相同的功能。你只能有一个函数,并以不同的线程启动它五次。

  • 你正在睡觉时锁定了互斥锁。这意味着其他线程将在线程休眠时阻塞。我想你在释放锁之后想要睡觉,以便其他线程可以在柜台上。

  • 在while循环条件下检查计数器时,您正在读取互斥锁保护之外的计数器。无论您是在阅读还是写作,都需要在访问共享资源时锁定互斥锁。如果你不这样做,你将有竞争条件。

  • 如果您遵循我的建议并在释放互斥锁后移动睡眠,则不需要调用pthread_yield,因为睡眠也会产生。