多线程程序中的错误
我必须制作一个具有共享变量(初始值 = 35 的计数器)和 5 个线程的程序。我必须编写程序,以便每个线程访问计数器的值并将其减 1。这应该持续到 counter = 0。
这就是我到目前为止的代码,但问题是只有一个线程将计数器的值递减至 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();
}
}
有人可以帮忙吗? 谢谢
I have to make a program which has a shared variable (counter with initial value = 35) and 5 threads. I have to make the program so that each thread accesses the value of the counter and decrements it by 1. This should continue until counter = 0.
This is what I have for the code so far, but the problem is that only one thread is decrementing the value of counter to 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();
}
}
Can anyone please help ?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
r
是一个 0 到 2 之间的随机数,但是你睡了rand
秒,这是一个函数的地址,它将被隐式转换为一个 unsigned int - 所以线程会休眠很长一段时间。请改用sleep(r);
。另外,请注意,您在不持有互斥锁的情况下读取了
counter
(在while(counter > 0)
中),这可能会导致程序无法正常工作,具体取决于架构、缓存和编译器优化。您应该锁定互斥锁,将counter
的值读取到局部变量,然后解锁互斥锁并检查该值是否为正。r
is a random number between 0 and 2, but you sleeprand
seconds, which is the address of a function, which will be implicitly casted to an unsigned int - so the thread will sleep for a very very long time. Usesleep(r);
instead.Also, note that you read
counter
while not holding the mutex (inwhile(counter > 0)
), which may lead to the program working incorrectly depending on architecture, caching and compiler optimizations. You should lock the mutex, read the value ofcounter
to a local variable, then unlock the mutex and check whether the value is positive.虽然 Antti 找到了一个很好的函数,但我还有一些评论要说:
您不需要五个相同的函数。您可以只有一个函数,并作为不同的线程启动它五次。
您正在睡觉,并且互斥体已锁定。这意味着当一个线程休眠时其他线程将阻塞。我认为你想在释放锁后睡眠,以便其他线程可以在计数器上。
当您在 while 循环的条件下检查计数器时,您正在读取互斥锁保护之外的计数器。当访问共享资源时,无论是读还是写,都需要锁定互斥锁。如果不这样做,就会遇到竞争条件。
如果您遵循我的建议并在互斥体释放后移动睡眠,则无需调用 pthread_yield,因为睡眠也会产生。
While Antti found a good one, I have a few more comments to make:
you don't need five identical functions. You can have only one function, and start it five times as different threads.
you are sleeping with the mutex locked. That means that the other threads will block while a thread sleeps. I think you want to sleep after releasing the lock, so that other threads can have at the counter.
You are reading the counter outside of mutex protection when you check the counter in the while loop's condition. You need to lock the mutex when you access the shared resource, no matter if you are reading or writing. If you don't then you'll have race conditions.
if you follow my advice and move the sleep after the mutex is released, then calling pthread_yield is not necessary, since a sleep also yields.