I'm learning POSIX pthreads and while using a mutex I started getting a weird output.
Every time I run the code it outputs a random number while I expect it to output 0. I checked the code and I could not figure out the reason why it happens so if can someone explain to me what is going wrong exactly it will be very appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int num = 0;
pthread_mutex_t mutex;
void* add(void* args)
{
int sign = *(int*) args;
for(int i = 0; i < 100; i++)
{
pthread_mutex_lock(&mutex);
num += sign;
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t pool[1000];
int plus = +1;
int minus = -1;
pthread_mutex_init(&mutex, NULL);
for(int i = 0; i < 500; i++)
pthread_create(&pool[i], NULL, add, &plus);
for(int i = 500; i < 1000; i++)
pthread_create(&pool[i], NULL, add, &minus);
for(int i = 0; i < 1000; i++)
pthread_join(pool[i], NULL);
printf("%d", num);
return 0;
}
the following proposed code:
cleanly compiles
properly checks for errors
properly initializes the mutex
performs the desired functionality
results in an output of 0
Note: function: pthread_mutex_init() is a valid function, but a initial value of NULL is not valid
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int num = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* add(void* args)
{
int sign = *(int*) args;
for(int i = 0; i < 100; i++)
{
pthread_mutex_lock(&mutex);
num += sign;
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main( void )
{
pthread_t pool[1000];
int plus = +1;
int minus = -1;
for(int i = 0; i < 500; i++)
if( pthread_create(&pool[i], NULL, add, &plus) != 0 )
{
perror( "pthread_create failed" );
pool[i] = 0;
}
for(int i = 500; i < 1000; i++)
{
if( pthread_create(&pool[i], NULL, add, &minus) != 0 )
{
perror( "pthread-create failed" );
pool[i] = 0;
}
}
for(int i = 0; i < 1000; i++)
{
if( pool[i] )
{
pthread_join(pool[i], NULL);
}
}
printf("%d", num);
return 0;
}
a run of the proposed code, on linux, results in:
0
Related
I want to Interpret how to reach this output for at least 5 different outputs.
And Modify the program to fix this problem.How Can I do it?
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 4
void *threadFunc(void *pArg)
{
int *p = (int*)pArg;
int myNum = *p;
printf("Thread number %d\n", myNum);
return 0;
}
int main(void)
{
int i;
pthread_t tid [NUM_THREADS];
for(i = 0; i < NUM_THREADS; i++)
{
pthread_create(&tid[i], NULL, threadFunc, &i);
}
for(i = 0; i < NUM_THREADS; i++)
{
pthread_join(tid [i], NULL);
}
return 0;
}
Thread function receives pointer to int. Memory it points to is shared between threads, so while thread function reads value of i it is changed by main thread. This is race condition.
You can fix it by storing individual i values for each thread:
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 4
void *threadFunc(void *pArg)
{
int *p = (int*)pArg;
int myNum = *p;
printf("Thread number %d\n", myNum);
return NULL; // thread function returns a pointer
}
int main(void)
{
int i;
pthread_t tid[NUM_THREADS];
int data[NUM_THREADS];
for (i = 0; i < NUM_THREADS; i++)
{
data[i] = i;
pthread_create(&tid[i], NULL, threadFunc, data+i); // `data+i` is equivalent to `&data[i]`
}
for (i = 0; i < NUM_THREADS; i++)
{
pthread_join(tid [i], NULL);
}
return 0;
}
Another option is to pass an integer as a pointer value. It doesn't require storage for each thread but may cause truncating problems because of int<->intptr_t conversion.
#include <stdio.h>
#include <pthread.h>
#include <inttypes.h> // for intptr_t
#define NUM_THREADS 4
void *threadFunc(void *arg)
{
int myNum = (intptr_t)arg;
printf("Thread number %d\n", myNum);
return NULL; // thread function returns a pointer
}
int main(void)
{
int i;
pthread_t tid[NUM_THREADS];
for (i = 0; i < NUM_THREADS; i++)
{
pthread_create(&tid[i], NULL, threadFunc, (void *)(intptr_t)i);
}
for (i = 0; i < NUM_THREADS; i++)
{
pthread_join(tid [i], NULL);
}
return 0;
}
#include <stdio.h>
#include <pthread.h>
void *runner(void * p)
{
int *line = p;
printf("line: %d\n", *line);
}
int main()
{
pthread_t tid[2];
for (int i = 0; i < 2; i++)
pthread_create(&tid[i], 0, runner, &i);
for (int i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
return 0;
}
For the above code I expect the output to be
line 0
line 1
But the output is actually
line 1
line 2
So what is wrong with this code? How did i get incremented? Do I have to pass structs to the runner function?
There's no guarantee that printf("line: %d\n", *line); line will finish before pthread_create returns, which means you have a race on i.
(The main thread tries to increment it and the new threads try to read it
via their argument pointer).
You can solve the problem by passing pointers to different objects (one per thread, optimally cache-aligned, but that hardly matters here):
#include <stdio.h>
#include <pthread.h>
void *runner(void * p)
{
int *line = p;
printf("line: %d\n", *line);
return 0;
}
int main()
{
pthread_t tid[2];
int ints[2];
for (int i = 0; i < 2; i++){
ints[i]=i;
if(pthread_create(&tid[i], 0, runner, &ints[i])) return 1;
}
for (int i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
return 0;
}
or by passing the i by value (by casting it to void*):
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
void *runner(void * p)
{
printf("line: %d\n", (int)(intptr_t)p);
return 0;
}
int main()
{
pthread_t tid[2];
int ints[2];
for (int i = 0; i < 2; i++){
if(pthread_create(&tid[i], 0, runner, (void*)(intptr_t)i)) return 1;
}
for (int i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
return 0;
}
I am currently working on the calculation of the Eratosthenes Sieve using C multithreading.
The goal is to first create a main thread that uses a split function to divide the exploration of the numbers on a number of threads.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *creat_thread(int *nbThreads);
void *SieveEratosthenes(int *tailleTab);
int* tab;
int sizeTab;
int nbTachesParThread=0;
int main(void)
{
int nbThreads;
int n;
do{
printf("Enter an integer > 1 : ");
scanf("%d", &n);
} while(n<2);
sizeTab = n+1;
tab = (int*)malloc(tailleTab*sizeof(int));
for (unsigned int i=0; i<tailleTab; i++)
{
tab[i] = 1;
}
do{
printf("Enter a number positive number of threads : ");
scanf("%d", &nbThreads);
} while(nbThreads<1);
pthread_t threadPrincipal;
if (pthread_create(&threadPrincipal, NULL, creat_thread, NULL)) {
perror("pthread_create");
return EXIT_FAILURE;
}
if (pthread_join(threadPrincipal, NULL)) {
perror("pthread_join");
return EXIT_FAILURE;
}
printf("The Prime numbers are : \n");
for(unsigned int i=0; i<sizeTab; i++)
{
if(tab[i]==1)
{
printf("%d\n", (i));
}
}
}
void *creat_thread(int *nbThreads)
{
int nbTachesParThread = (int) sqrt(sizeTab) / nbThreads;
pthread_t* threads = (pthread_t*)malloc(nbThreads*sizeof(pthread_t));
int plageThreadi = nbTachesParThread;
for(int i = 0; i < nbThreads; ++i)
pthread_create (&threads[i], NULL, SieveEratosthenes, plageThreadi);
plageThreadi += nbTachesParThread;
}
void *SieveEratosthenes(int *plageThread)
{
for( int i=(plageThread - nbTachesParThread); i<=plageThread; i++)
{
if (tab[i] == 1)
{
for (int j = i*i; j<sizeTab; j += i)
{
tab[j]=0;
}
}
}
}
I tried to implement a code but I have an error at runtime:
segmentation error (core dumped)
On top of the issue mention in my comment here there is more to fix:
1st of all a PThread function needs to be of type void *(*)(void*). The ones used by the code are of type void *(*)(int*). Not good.
2ndly the code misses to join the work-threads, therefore the distributing thread ends after having created all workers, then it gets joined in main(), which then accesses the variables the workers are most likely are still working on causing undefined behaviour be doing so and then ends, ending the process. Ending the process cancels all worker-threads.
I followed your advice and created a structure to contain the variables that will be used by all threads.
However I noticed that sometimes it works (it displays the prime numbers well) but sometimes it doesn't work and it displays either only 0 or all the numbers from 0 to i.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *creat_thread(void* arg);
void *SieveEratosthenes(void* arg);
struct param
{
int* tab;
int sizeTab;
int nbTachesParThread;
int nbThreads;
int plageThreadi;
int plageThreadPrecedent;
};
int main(void)
{
struct param p;
int n;
do{
printf("Enter an integer > 1 : ");
scanf("%d", &n);
} while(n<2);
p.sizeTab = n+1;
p.tab = (int*)malloc(p.sizeTab*sizeof(int));
for (unsigned int i=0; i<p.sizeTab; i++)
{
p.tab[i] = 1;
}
do{
printf("Enter a number positive number of threads : ");
scanf("%d", &p.nbThreads);
} while(p.nbThreads<1);
pthread_t threadPrincipal;
if (pthread_create(&threadPrincipal, NULL, (void*)creat_thread, &p)) {
perror("pthread_create");
return EXIT_FAILURE;
}
if (pthread_join(threadPrincipal, NULL)) {
perror("pthread_join");
return EXIT_FAILURE;
}
printf("The Prime numbers are : \n");
for(unsigned int i=0; i<p.sizeTab; i++)
{
if(p.tab[i]==1)
{
printf("%d\n", i);
}
}
}
void *creat_thread(void* arg)
{
struct param *args = (void*)arg;
args->nbTachesParThread = (int) sqrt(args->sizeTab) / args->nbThreads;
pthread_t* threads = (pthread_t*)malloc(args->nbThreads*sizeof(pthread_t));
args->plageThreadi = args->nbTachesParThread;
for(int i = 0; i < args->nbThreads; ++i)
{
pthread_create (&threads[i], NULL, (void*)SieveEratosthenes, &(*args));
args->plageThreadPrecedent = args->plageThreadi;
args->plageThreadi += args->nbTachesParThread;
}
for(int i = 0; i < args->nbThreads; ++i)
{
pthread_join(threads[i], NULL);
}
pthread_exit(NULL);
}
void *SieveEratosthenes(void* arg)
{
struct param *args = (void *)arg;
for(int i=(args->plageThreadPrecedent); i<=args->plageThreadi; i++)
{
if (args->tab[i] == 1)
{
for (int j = i*i; j<args->sizeTab; j += i)
{
args->tab[j]=0;
}
}
}
pthread_exit(NULL);
}
In the main() function, move the calls to pthread_create() and pthread_join() outside of the if statement. These calls should be made regardless of whether or not the pthread_create() call succeeds.
In the SieveEratosthenes() function, the loop that marks composite numbers as 0 should start from i * i, not i. This is because any composite number can be written as the product of two prime numbers, and one of those prime numbers must be less than or equal to the square root of the composite number. Therefore, if a number i is composite, it must have a prime factor less than or equal to the square root of i.
In the creat_thread() function, move the call to pthread_join() inside the loop that creates the threads. This will ensure that each thread has completed before the next one is created.
In the creat_thread() function, initialize the plageThreadPrecedent variable to 2, since this is the first prime number.
I've modified my code so actually I have no more error code but once I have entered the 2 variables (number to calculate + number of threads), the program runs but displays nothing.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *creat_thread();
void *SieveEratosthenes();
int* tab;
int sizeTab = 0;
int nbTachesParThread=0;
int nbThreads = 0;
int plageThreadi = 0;
int plageThreadPrecedent = 0;
int main(void)
{
int n;
do{
printf("Enter an integer > 1 : ");
scanf("%d", &n);
} while(n<2);
sizeTab = n+1;
tab = (int*)malloc(sizeTab*sizeof(int));
for (unsigned int i=0; i<sizeTab; i++)
{
tab[i] = 1;
}
do{
printf("Enter a number positive number of threads : ");
scanf("%d", &nbThreads);
} while(nbThreads<1);
pthread_t threadPrincipal;
if (pthread_create(&threadPrincipal, NULL, creat_thread, NULL)) {
perror("pthread_create");
return EXIT_FAILURE;
}
if (pthread_join(threadPrincipal, NULL)) {
perror("pthread_join");
return EXIT_FAILURE;
}
printf("The Prime numbers are : \n");
for(unsigned int i=0; i<sizeTab; i++)
{
if(tab[i]==1)
{
printf("%d\n", (i));
}
}
}
void *creat_thread()
{
int nbTachesParThread = (int) sqrt(sizeTab) / nbThreads;
pthread_t* threads = (pthread_t*)malloc(nbThreads*sizeof(pthread_t));
int plageThreadi = nbTachesParThread;
for(int i = 0; i < nbThreads; ++i)
{
pthread_create (&threads[i], NULL, SieveEratosthenes, NULL);
pthread_join(threads[i], NULL);
plageThreadPrecedent = plageThreadi;
plageThreadi += nbTachesParThread;
}
for(int i = 0; i < nbThreads; ++i)
{
pthread_join(threads[i], NULL);
}
pthread_exit(NULL);
}
void *SieveEratosthenes()
{
for(int i=(plageThreadPrecedent); i<=plageThreadi; i++)
{
if (tab[i] == 1)
{
for (int j = i*i; j<sizeTab; j += i)
{
tab[j]=0;
}
}
}
pthread_exit(NULL);
}
I have got a project from my university for critical section problem of n processes. I have made a code for 2 processes in c But I could not figure out how to get it working for n process . The code is in C for linux threads.
Here is code for 2 Processes.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int flag[2];
int turn;
const int MAX = 1e9;
int ans = 0;
void lock_init(){
flag[0]=flag[1]=0;
turn = 0;
}
void lock(int self){
flag[self]=1;
turn = 1-self;
while(flag[1-self]==1 && turn == 1-self);
}
void unlock(int self){
flag[self]=0;
}
void* func(void *s){
int i=0;
int *limitptr = (int*) s;
int self = *limitptr;
printf("Thread %d in queue for critical section\n",self);
lock(self);
printf("Thread %d in critical section\n",self);
for(i=0;i<MAX;i++){
ans++;
}
printf("Thread %d done counting\n",self);
printf("Thread %d is exiting critical section\n",self);
unlock(self);
}
int main(){
pthread_t p1, p2;
int a=0,b=1;
lock_init();
pthread_create(&p1, NULL, func, &a);
pthread_create(&p2, NULL, func, &b);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("Exiting Main\n");
return 0;
}
Any help would be appreciated.
Thank You. :)
use a mutex
#include <pthread.h>
declare the mutex like so:
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
then at the beginning of a critical section call:
pthread_mutex_lock( &myMutex );
and at the end of the critical section call:
pthread_mutex_unlock( &myMutex );
it does not matter how many threads are using that critical section, only one thread will be able to access it at a time
Thank You for your valuable time and answers.
I Found A solution for My problem and thought of sharing it.I Implemented Bakery Algorithm In C.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
int N;
int global = 10;
int entering[100];
int number[100];
int max(int number[100]) {
int i = 0;
int maximum = number[0];
for (i = 0; i < N; i++) {
if (maximum < number[i])
maximum = number[i];
}
return maximum;
}
void lock(int i) {
int j = 0;
entering[i] = TRUE;
number[i] = 1 + max(number);
entering[i] = FALSE;
for (j = 0; j < N; j++) {
while (entering[j]);
while (number[j] != 0 && (number[j] < number[i] || (number[i] == number[j]) && j < i)) {}
}
}
void unlock(int i) {
number[i] = 0;
}
void *fn(void *integer) {
int i = (int) integer;
lock(i);
printf("\n\n-----------Process %d---------",i);
printf("\nProcess %d is Entering Critical Section\n",i);
global++;
printf("%d is the value of global \n",global);
printf("Process %d is leaving Critical Section\n",i);
printf("----------------------------------\n\n");
unlock(i);
}
int main()
{
printf("Enter Number of Process\n");
scanf("%d",&N);
int th[N];
void *fn(void *);
pthread_t thread[N];
int i = 0;
for (i = 0; i < N; i++) {
th[i] = pthread_create(&thread[i], NULL, fn, (void *)i);
pthread_join(thread[i], NULL);
}
return EXIT_SUCCESS;
}
Again Thank You :)
I'm working on a project that requires somewhat similar functionality to the program below so I've tried to create a simpler program to debug my larger program. The threads I'm creating are returning values that are inconsistent with their expected output but their return values are not random. It almost seems like the threads are returning the values from other threads or that the variable they are returned to ("tmp") is updating.
The expected output should be...
0 1
1 2
#include <stdio.h>
#include <pthread.h>
struct Numbers {
int x;
int y;
};
void *go(void* param)
{
struct Numbers* nums = (struct Numbers*) param;
int sum = nums -> x + nums -> y;
return (void*) sum;
}
int main()
{
int result[2][2];
int tmp;
pthread_t thread[2][2];
int i, j;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
struct Numbers nums;
nums.x = i;
nums.y = j;
pthread_create(&thread[i][j], NULL, go, &nums);
}
}
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
pthread_join(thread[i][j], (void*) &tmp);
result[i][j] = tmp;
}
}
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
printf("%d\t", result[i][j]);
}
printf("\n");
}
return 0;
}
You're passing the address of a variable that probably won't exist once the thread begins executing, or at least will be seen by multiple threads, or is a data race as one thread writes it while the others read it.
A general solution is to dynamically allocate both the arguments and results of your thread, and let the caller and thread communicate that way.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct threadargs {
int x;
int y;
};
struct threadresults {
int sum;
int product;
};
void* threadfunc(void* args_void) {
// Get thread args in usable type.
struct threadargs* args = args_void;
struct threadresults* results = NULL;
//Compute.
int sum = args->x + args->y;
int product = args->x * args->y;
// Return the result.
results = malloc(sizeof(*results));
results->sum = sum;
results->product = product;
free(args);
return results;
}
int main()
{
pthread_t thread[2][2];
struct threadresults* results[2][2] = {0};
int i, j;
for (i = 0;i < 2; ++i) {
for (j = 0; j < 2; ++j) {
struct threadargs* args = malloc(sizeof(*args));
args->x = i;
args->y = j;
pthread_create(&thread[i][j], NULL, threadfunc, args);
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
void* result;
pthread_join(thread[i][j], &result);
results[i][j] = result;
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
printf("sum: %d\tproduct: %d\n",
results[i][j]->sum, results[i][j]->product);
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
free(results[i][j]);
}
}
return 0;
}