This is my code. It's very simple.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *func(void *arg)
{
printf("ID=%d\n", *(int*)arg);
pthread_exit(NULL);
}
int main()
{
pthread_t pt[4];
int i;
for (i = 0; i < 4; i++)
{
int temp = i;
pthread_create(&pt[i], NULL, func, (void*)&temp);
}
sleep(1);
return 0;
}
I compiled it:
gcc p_test.c -lpthread
I ran it. It printed 2 2 3 3. I ran it again. It printed 2 3 3 2.
My problem is:
Why was 2 or 3 printed twice?
Why didn't it print 1 3 2 0 or any other results?
The major problem here is that you're taking the address of the local variable temp, and then using that pointer outside the scope of the variable - as soon as you exit one iteration of the loop, your pointer to temp becomes invalid and you must not dereference it.
You're passing a pointer to a temporary variable into the thread creation function and this temporary goes out of scope at the end of the loop block. It would seem to me that the temporary address is being reused by the compiler and so that when the threads are executing, they see the same address location.
If you do:
int *temp = malloc(sizeof(int));
*temp = i;
pthread_create(&pt[i], NULL, func, (void*)temp);
instead, you should see the results you expect.
In this case, the thread function needs to free the int after it is printed it to avoid a memory leak.
Also, it's better practice to pthread_join() the threads that you're waiting for rather than just sleep()ing.
because it prints temp, all threads shares the memory(why temp is "shared" is explained by TheJuice), so all threads "share" temp . Use a mutex or make temp a private variable.
Private Variables in Threads
Or you can use phtread_join like this:
int main()
{
pthread_t pt[4];
int i;
for (i =0 ; i < 4; i++)
{
pthread_create(&pt[i], NULL, func, (void*)&i);
pthread_join(pt[i],NULL);
}
//sleep(1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *func(void* arg)
{
printf("ID=%d\n", (int)arg);
pthread_exit(NULL);
return 0;
}
int main()
{
pthread_t pt[4];
int i;
for (i =0 ; i < 4; i++)
{
pthread_create(&pt[i], NULL, func, (void*)i);
pthread_join(pt[i],NULL);
}
return 0;
}
Related
How should i properly sync threads with mutex?
I'm trying a simple "sync" using mutex, something really small, like just printing a string containing the number of the thread. snippet here:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define MAX_RESOURCE 5
#define NO_THREADS 5
int res_available = MAX_RESOURCE;
pthread_mutex_t mtx;
struct count { int no;};
void *
use_res(void *v) {
pthread_mutex_lock(&mtx);
struct count *p = (struct count *) v;
printf("--thread no %d :" p->nr);
return NULL;
}
int main(){
pthread_t thr[NO_THREADS];
pthread_mutex_init(&mtx, NULL);
for(int i=0; i<N0_THREADS; i++){
struct count *c = malloc(sizeof(struct count));
c->nr = i;
pthread_create(thr[i], NULL, use_res, c))
}
for(int i=0; i<NO_THREADS; i++) {
pthread_join(thr[i], NULL);
}
return 0;
}
Fact is, when executed, the sync doesn't actually occur, actually, what it does occur, is still that "race condition", making the program to print something else everytime.
My question is, how do i stop this race condition? I don't know if i'm using correctly this lock and unlock thing.
You need to release mutex when your thread function finish, also add \n at the end of print, because stdout will buffer this text:
void *
use_res(void *v) {
pthread_mutex_lock(&mtx);
struct count *p = (struct count *) v;
printf("--thread no %d :\n" p->no);
pthread_mutex_unlock(&mtx);
return NULL;
}
I'm currently confused as to why the following code won't print the following:
My value is 0
My value is 1
My value is 2
Every time I run this I either get 1-2 printed lines or nothing and the program just sits their until I ctrl-c. I feel like it might have something to do with me using the same condition variable and mutex with 3 different threads, would this be correct? Any explanations are greatly appreciated.
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
struct id_holder
{
int id;
};
pthread_mutex_t intersectionMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t directionCondition = PTHREAD_COND_INITIALIZER;
struct id_holder * holder;
void * logic(void* val)
{
struct id_holder * id_struct = (struct id_holder *) val;
pthread_cond_wait(&directionCondition, &intersectionMutex);
printf("My value is %d\n", id_struct->id);
free(id_struct);
return NULL;
}
int main(void)
{
pthread_t threads[3];
for(int i = 0; i <3; i++)
{
holder = (struct id_holder *) malloc(sizeof(struct id_holder));
holder->id = i;
pthread_create(&threads[i], NULL, logic, holder);
}
for(int i = 0; i < 3; i++)
{
sleep(1);
pthread_cond_signal(&directionCondition);
}
for(int i = 0; i < 3; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
When condition is waited for or signalled, it must be done under the lock, otherwise the behavior is unpredictable as it could into race condition. Therefore your code should look like:
pthread_mutex_lock(&intersectionMutex);
pthread_cond_wait(&directionCondition, &intersectionMutex);
pthread_mutex_unlock(&intersectionMutex);
And the same for main (you can move the lock outside the loop if you wish):
for(int i = 0; i < 3; i++) {
sleep(1);
pthread_mutex_lock(&intersectionMutex);
pthread_cond_signal(&directionCondition);
pthread_mutex_unlock(&intersectionMutex);
}
Still the code is not 100% safe as the main thread can signal the condition before the child thread invokes the wait. Although it's highly improbable here due to sleep() in the main function, generally there should be a variable that identifies whether the wait is actually needed or not. In other words, conditions are not queue but can be used to create queue.
i am trying to implement Dining Philosophers in C using Resource hierarchy solution. when i am using valgrind everything goes fine. Unfortunately when i done this using console im getting random seqfaults. One time my program will be succesful,one time it will broke on the beginning. I would be grateful if anybody could point where i did mistake and why it's 100% succesfull.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_PHILOSPHERS 5
sem_t forks[NUM_PHILOSPHERS];
void *philosopher(void *param){
printf("Thread created!");
int *id = (int *)param;
int L = 0;
sem_t* Myforks[2];
int par = *id;
if(par == 4){
Myforks[0] = &forks[4];
Myforks[1] = &forks[0];
}else{
Myforks[0] = &forks[par];
Myforks[1] = &forks[par+1];
}
while(L!=5){
printf("Eat spaghetti!",*id);
sem_wait(Myforks[0]);
sem_wait(Myforks[1]);
//.....
printf("EAT spaghetti!",*id);
sem_post(Myforks[1]);
sem_post(Myforks[0]);
L=L+1;
}
pthread_exit(NULL);
}
int main(){
int i;
pthread_t threads[NUM_PHILOSPHERS];
for(i = 0; i < NUM_PHILOSPHERS; i++)
sem_init(&forks[i], 0, 1);
for(i = 0; i < NUM_PHILOSPHERS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)&i);
return 0;
}
int i;
...
for(i = 0; i < NUM_PHILOSPHERS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)&i);
^^
Passing a pointer to a local variable isn't going to work. You're passing the same address to all of the threads, so there's an inherent race condition. You point them a pointer to i and them almost immediately you increment i. What value will they read when they access *param? Who knows!
You'll want to create an array with NUM_PHILOSPHERS (sic) slots in it and pass a different address to each thread. You'll also want to make sure that array isn't destroyed when main() exits—i.e., make the array global or static, not local.
Here is a block of code that creates a number of threads provided by the user, each thread then generates a random number and calculates its squareroot. I cannot figure out why the threads are getting the same ID, line 64 is the culprit as it is where the threads are being created. I suspect that there is something happening in the loop that is causing the threads to all be generated at the same time.
////////////////////////////////////////////////
//
//
// Zach
//
//
//
//
////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *squareroot(void *num1)
{
int *id = (int *)num1;
int incoming = rand()/100;
float *outgoing = (float *)malloc(sizeof(float));
printf("%d \n", *id);
printf("%d\n", incoming);
*outgoing = 5.000;
//Calculate the square root of the number passed to the function
*outgoing = sqrt(incoming);
return outgoing;
}
int main(int argc, char* argv[])//testing funcion
{
srand(time(NULL));
int i, j;
int *temp = (int *)malloc(sizeof(int));
if (argc != 2)
{
printf ("ERROR: Enter a number\n");
return 1;
}
int loop = atoi(argv[1]); //grabbing the integer supplied by user
pthread_t thread_id[loop];
void *exit_status;
float *thread_result;
for(i = 0; i < loop; i++)
{
pthread_create(&thread_id[i], NULL, squareroot, &i);
}
for(j = 0; j < loop; j++)
{
pthread_join(thread_id[j], &exit_status);
thread_result = (float *)exit_status;
printf("%f\n", *thread_result);
}
}
I think what is happening is that your loop finishes creating all the threads (or at least some of them) before any of the threads actually run and extract their unique id.
Because you're passing a pointer to i, when each thread finally gets around to checking its parameter, i is already finished... Or at least partway through. The danger is that multiple threads might see the same value for i. It's even worse that you never copy the value out of that pointer - you always dereference it. That means it might change in the middle of your thread's execution.
What you should do instead is pretend it is a pointer:
pthread_create(&thread_id[i], NULL, squareroot, (void*)i);
And in your thread function:
int id = (int)num1;
This works because the pointer is passed by value. Whatever value you provide is the value that goes into the thread function. Previously it didn't work because you passed a pointer to a value that could change in another thread.
PS: Don't forget to free the result from each thread in your loop at the end. At the moment you're not cleaning up memory that you allocated.
While working with Threads in C, I'm facing the warning
"warning: cast to pointer from integer of different size"
The code is as follows
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<pthread.h>
void *print(void *id)
{
int a=10;
printf("My thread id is %ld\n",pthread_self());
printf("Thread %d is executing\n",id);
return (void *) 42;
}
int main()
{
pthread_t th[5];
int t;
int i;
int status;
void *ret;
for(i=0;i<5;i++)
{
status=pthread_create(&th[i],NULL,print,(void *)i); //Getting warning at this line
if(status)
{
printf("Error creating threads\n");
exit(0);
}
pthread_join(th[i],&ret);
printf("--->%d\n",(int *)ret);
}
pthread_exit(NULL);
}
Can anybody explain how to pass an integer to a function which receives (void * ) as a parameter?
This is a fine way to pass integers to new pthreads, if that is what you need. You just need to suppress the warning, and this will do it:
#include <stdint.h>
void *threadfunc(void *param)
{
int id = (intptr_t) param;
...
}
int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);
Discussion
This may offend your sensibilities, but it's very short and has no race conditions (as you'd have if you used &i). No sense in writing a few dozen lines of extra code just to get a bunch of numbered threads.
Data races
Here is a bad version with a data race:
#include <pthread.h>
#include <stdio.h>
#define N 10
void *thread_func(void *arg)
{
int *ptr = arg;
// Has *ptr changed by the time we get here? Maybe!
printf("Arg = %d\n", *ptr);
return NULL;
}
int main()
{
int i;
pthread_t threads[N];
for (i = 0; i < N; i++) {
// NO NO NO NO this is bad!
pthread_create(&threads[i], NULL, thread_func, &i);
}
for (i = 0; i < N; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
Now, what happens when I run it with the thread sanitizer?
(Also, check out how it prints "5" twice...)
==================
WARNING: ThreadSanitizer: data race (pid=20494)
Read of size 4 at 0x7ffc95a834ec by thread T1:
#0 thread_func /home/depp/test.c:9 (a.out+0x000000000a8c)
#1 <null> <null> (libtsan.so.0+0x000000023519)
Previous write of size 4 at 0x7ffc95a834ec by main thread:
#0 main /home/depp/test.c:17 (a.out+0x000000000b3a)
Location is stack of main thread.
Thread T1 (tid=20496, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x0000000273d4)
#1 main /home/depp/test.c:18 (a.out+0x000000000b1c)
SUMMARY: ThreadSanitizer: data race /home/depp/test.c:9 thread_func
==================
Arg = 1
Arg = 2
Arg = 3
Arg = 4
Arg = 5
Arg = 6
Arg = 7
Arg = 8
Arg = 9
Arg = 5
ThreadSanitizer: reported 1 warnings
you can do something like this:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
struct th {
pthread_t thread;
int id;
int ret;
};
void *print(void *id) {
int a=10;
struct th *self = (struct th *) id;
printf("My thread id is %ld\n",pthread_self());
printf("Thread %d is executing\n",self->id);
self->ret = random();
return;
}
int main(void) {
struct th th[5];
int t;
int i;
int status;
void *ret;
for(i=0;i<5;i++) {
th[i].id = i;
status=pthread_create(&th[i].thread,NULL,print,&th[i]); //Getting warning at this line
if(status) {
printf("Error creating threads\n");
exit(0);
}
}
for (i=0;i<5;i++) {
pthread_join(th[i].thread,&ret);
printf("%d--->%d\n",th[i].id,th[i].ret);
}
pthread_exit(NULL);
}
will output:
My thread id is 4496162816
My thread id is 4497870848
My thread id is 4498944000
My thread id is 4498407424
Thread 0 is executing
Thread 1 is executing
My thread id is 4499480576
Thread 3 is executing
Thread 2 is executing
0--->1804289383
Thread 4 is executing
1--->846930886
2--->1714636915
3--->1681692777
4--->1957747793
passing a unique pointer to each thread wont race, and you can get/save any kind of information in the th struct
you can pass the int value as void pointer like (void *)&n where n is integer, and in the function accept void pointer as parameter like void foo(void *n);and finally inside the function convert void pointer to int like, int num = *(int *)n;. this way you won't get any warning.
change:
status=pthread_create(&th[i],NULL,print,(void *)i);
to:
status=pthread_create(&th[i],NULL,print,(reinterpret_cast<void*>(i));
The reinterpret_cast makes the int the size of a pointer and the warning will stop. Basically its a better version of (void *)i.