I have global structure pointer which i have done a malloc (array of 10 structures) and i have sent one instance of this structure to each thread, and before passing this structure instance as argument to pthread_create(), am updating the structure member value. Inside each thread i will lock and print the member value.
I have created another thread, in which i am passing the entire structure instance, i am locking each structure instance and printing it, but every time it prints 0. Can you please suggest what changes i have to make.
I dont want to use any thread conditions, as i am sleeping in each thread for a thread switch.
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
struct lock_check{
int value;
pthread_mutex_t lock;
};
struct lock_check *check;
void* trythis(void *arg)
{
struct lock_check *thread = (struct lock_check *)arg;
while(1){
pthread_mutex_lock(&thread->lock);
printf("Inside Thread with value:%d\n", thread->value);
pthread_mutex_unlock(&thread->lock);
sleep(1);
}
return NULL;
}
void* printthis(void *arg)
{
printf("Entering printthis thread\n");
struct lock_check *print_thread = (struct lock_check *)arg;
for(int i = 0; i < 10; i++){
pthread_mutex_lock(&print_thread[i].lock);
printf("Printing value :%d\n", print_thread[i].value);
pthread_mutex_unlock(&print_thread[i].lock);
}
return NULL;
}
int main(void)
{
int i = 0;
int error;
check = malloc(sizeof(struct lock_check) * 10);
pthread_t tid[10];
pthread_t tid_read;
for (int i = 0; i < 10; i++) {
check[i].value = i;
error = pthread_create(&(tid[i]), NULL, &trythis, &check[i]);
if (error != 0)
printf("\nThread can't be created :[%s]", strerror(error));
}
sleep(5);
printf("creating printthis thread\n");
error = pthread_create(&tid_read, NULL, &printthis, &check);
for (int i = 0; i < 10; i++) {
pthread_join(tid[i], NULL);
}
pthread_join(tid_read, NULL);
return 0;
}
error = pthread_create(&tid_read, NULL, &printthis, &check);
pthread_create is expecting void * but you are passing struct lock_check ** having undefined behavior.
Change it to.
error = pthread_create(&tid_read, NULL, &printthis, check);
Related
This issue is definitely the source of a stupid mistake, but for the life of me I cannot get to the bottom of it.
I'm writing a much larger program, but I've narrowed down a constant segfault error that is coming up whenever I call pthread_join. I've included the relevant code below, hopefully someone can help me figure out what I'm doing wrong. Cheers :)
Functions for managing pthreads
void *scalloc(size_t nmemb, size_t size)
{
void *p;
p = calloc(nmemb, size);
if (p == NULL)
sys_error("Error allocating memory block (calloc).", 1);
return p;
}
pthread_t *new_thread_array(int n)
{
return scalloc(n, sizeof(pthread_t));
}
int spthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
{
int ret;
if ((ret = pthread_create(&thread, attr, start_routine, arg)) != 0)
sys_error("Error at pthread_create.", ret);
return 0;
}
int spthread_join(pthread_t thread, void **retval)
{
int ret;
if ((ret = pthread_join(thread, retval)) != 0)
sys_error("Error at pthread_join.", ret);
return 0;
}
int create_threads(pthread_t *thread_arr, int n, const pthread_attr_t *attr,
void *(*start_routine) (void *), void **arg_arr)
{
for (int i = 0; i < n; i++) {
spthread_create(&thread_arr[i], attr, start_routine, arg_arr[i]);
debug("created thread %d", i);
}
return 0;
}
int join_threads(pthread_t *thread_arr, int n, void **ret_arr)
{
debug("Starting join");
for (int i = 0; i < n; i++) {
if (ret_arr != NULL)
spthread_join(thread_arr[i], ret_arr[i]);
else {
debug("Attempting to join %d", i);
spthread_join(thread_arr[i], NULL);
debug("Joined %d", i);
}
}
return 0;
}
Test code that produces the error
void *threadfunc(void *id)
{
fflush(stdout);
fprintf(stdout, "Thread %d printing.\n", *(int *)id);
fflush(stdout);
return;
}
int threadtest(int nodes)
{
int ret;
int *targs = scalloc(nodes, sizeof(int));
int *pass[nodes];
for (int i = 0; i < nodes; i++) {
targs[i] = i;
pass[i] = &targs[i];
}
printf("Starting L1 thread test...\n");
pthread_t *threads = new_thread_array(nodes);
debug("Allocated pthread array for %i threads.", nodes);
create_threads(threads, nodes, NULL, &threadfunc, pass);
join_threads(threads, nodes, NULL);
debug("Successfully joined %i threads.", nodes);
free(targs);
free(threads);
return 0;
}
int main()
{
return threadtest(5);
}
Finally, here is the output of running the function threadtest, confirming that the segfault (appears) to occur in the parent thread, at the call to pthread_join.
Starting L1 thread test...
Allocated pthread array for 5 threads.
created thread 0
created thread 1
Thread 0 printing.
created thread 2
Thread 1 printing.
Thread 2 printing.
created thread 3
Thread 3 printing.
created thread 4
Thread 4 printing.
Starting join
Attempting to join 0
zsh: segmentation fault ./tests/L1tests
I am writing a multi-threaded application that reads a file and seeks for a word in chunks of it a thread has in memory.
A thread needs to asynchronously close other threads looking for that word if it is first to find it.
The problem is when a word is found and other threads are being closed the program does not terminate (in 6 out of 10 executions). I have checked in gdb that one thread does not exit. It happens even when I do not call waitforthreads(n_threads).
// [...]
FILE* f;
pthread_mutex_t mutex;
pthread_t* threads;
int n_threads;
int allread;
// [...]
int main(int argc, char* argv[]) {
// [...]
threads = (pthread_t*) calloc(n_threads, sizeof(pthread_t));
pthread_mutex_init(&mutex, NULL);
runthreads(f, word, n_threads, n_records);
waitforthreads(n_threads);
pthread_mutex_destroy(&mutex);
// [...]
}
void runthreads(FILE* f, char* w, int n_threads, int n_records) {
struct targs_t args = {w, n_records};
for (int i=0; i<n_threads; i++)
pthread_create(&threads[i], NULL, findword, (void*) &args);
}
void waitforthreads(int N) {
for (int i=0; i<N; i++)
if(pthread_join(threads[i], NULL))
exit_(6);
}
void* findword(void* arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
struct targs_t* args = (struct targs_t*) arg;
int max_length = args->n_records * sizeof(record_t);
record_t* records = malloc(max_length);
int found = 0;
while (!allread && !found) {
pthread_mutex_lock(&mutex);
// allread is being set in the function below
// if the whole file has been read
readRecords((char*) records, args->n_records, f);
pthread_mutex_unlock(&mutex);
for (int i=0; i<args->n_records; i++)
if (strlen(records[i].text) == 0) break;
else if (strstr(records[i].text, args->word) != NULL) {
notifyfound(pthread_self(), records[i].id);
found = 1;
break;
}
}
free(records);
return NULL;
}
void notifyfound(pthread_t tid, int id) {
printf("Found: %d (%ld)\n", id, (long) tid);
for (int i=0; i<n_threads; i++)
if (threads[i] && !pthread_equal(threads[i], tid)) {
printf(" closing %ld\n", (long) threads[i]);
pthread_cancel(threads[i]);
}
printf(" finished closing\n");
}
This has to do with cancellation points, although the specifics are hard to come by since you haven't shared a minimal example. My diagnosis is either
6/10 times you have at least one thread waiting for a mutex, and other one in readRecords, which will cancel and not free the mutex. Setup cancellation handlers with pthread_cleanup_push and pthread_cleanup_pop which will free your mutex, and read the manual for pthread_cancel. See related pthread_cleanup_push causes Syntax error for some references.
Some of your threads are not detecting the cancellation - try using pthread_testcancel to setup a guaranteed cancellation point.
Here is some code that fixes these sorts of problems, by adding a cancellation check and mutex cleanup.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
FILE* f;
pthread_mutex_t mutex;
pthread_t* threads;
int n_threads = 3;
int allread;
long int count = 0;
int *thread_ids;
int global_quit = 0;
#define MAX 99999
void waitforthreads(int N) {
printf("waiting for %d threads\n", N);
for (int i=0; i<N; i++)
{
printf("thread %d | %d\n", i, threads[i]);
if(pthread_join(threads[i], NULL))
{
printf("problem\n");
exit(6);
}
}
printf("done.\n");
}
void notifyfound(pthread_t tid, int count) {
printf("%d | %d got big number\n", count, pthread_self());
for (int i=0; i<n_threads; i++)
if (threads[i] && !pthread_equal(threads[i], tid)) {
printf(" closing '%ld'\n", (long) threads[i]);
pthread_cancel(threads[i]);
}
global_quit = 1;
printf(" finished closing\n");
}
void waiting_thread_cleanup(void *arg)
{
pthread_mutex_unlock((pthread_mutex_t *)arg);
}
void* do_thing(void* arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
int* id = (int *)arg;
int quit = 0;
while (!allread) {
pthread_mutex_lock(&mutex);
pthread_cleanup_push(waiting_thread_cleanup, (void *)&mutex); /* must be paired with pop. */
if(count++==MAX)
{
notifyfound(pthread_self(), *id);
quit=1;
}
else if(count % 10000 == 0)
printf("[%d] - %d\n", *id, count);
pthread_testcancel(); /* required to allow for the cancel to ever be 'detected' other functions are sufficient as well. */
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(1); /* if this isn't here, this will occassionally hand because the mutex isn't freed. */
if(quit==1)
{
printf("%d | %d quitting\n", *id, pthread_self());
break;
}
}
return NULL;
}
void runthreads(FILE* f, int n_threads) {
for (int i=0; i<n_threads; i++)
pthread_create(&threads[i], NULL, do_thing, &(thread_ids[i]));
}
int main(int argc, char* argv[]) {
threads = (pthread_t*) calloc(n_threads, sizeof(pthread_t));
thread_ids = (int*) calloc(n_threads, sizeof(int));
for(int i=0;i<n_threads;i++)
thread_ids[i] = i;
pthread_mutex_init(&mutex, NULL);
runthreads(f, n_threads);
waitforthreads(n_threads);
pthread_mutex_destroy(&mutex);
}
New to C, I was reading here about how to properly pass an argument to a thread. What about if this argument needed to be passed to multiple threads? Where/how should I use free()? Say:
void *foo(void *i) {
int a = *((int *) i);
while(1){
printf("foo running \n");
sleep(1);
}
}
void *bar(void *i) {
int a = *((int *) i);
while(1){
printf("bar running \n");
sleep(1);
}
}
int main() {
pthread_t threads[2];
int i;
for (i = 0; i < 2; i++ ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(1);
}
*arg = i;
pthread_create(&threads[0], NULL, foo, arg);
pthread_create(&threads[1], NULL, bar, arg);
}
for (i = 0; i < 2; i++){
pthread_join(threads[i],NULL);
}
return 0;
}
Is calling free(arg); in main after spawning the threads the same thing / safe?
If all threads needs the exact same argument, and they are not modifying the argument, there's no need to allocate it dynamically at all, instead just declare it as a variable at function scope in the main function. If there's no dynamic allocation, there's no need to free it.
On the other hand if you need separate arguments in a loop like you do, you need to keep track of all arguments, for example using an array:
// Rest of program...
#define NUMBER_OF_ITERATIONS 2
int main(void)
{
int args[NUMBER_OF_ITERATIONS];
pthread_t threads[NUMBER_OF_ITERATIONS][2];
// Create threads
for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
{
args[i] = i;
pthread_create(&threads[i][0], NULL, foo, &args[i]);
pthread_create(&threads[i][1], NULL, bar, &args[i]);
}
// Wait for threads to finish
for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
{
pthread_join(threads[i][0]);
pthread_join(threads[i][1]);
}
return 0;
}
The program above also solves another problem you have, when you create a total of four threads but only join two.
You need to make sure both threads have finished before calling free(arg).
That means you can do it after you call pthread_join on both threads.
for (i = 0; i < 2; i++){
pthread_join(threads[i],NULL);
}
free(args);
I keep getting a seg fault (core dump) after pthread_join in my program. It prints out the expected result just fine, but seg faults when joining the thread. I have looked at several other discussions on this topic, but none of the suggested solutions seem to work in my case. Here is what my compile command looks like (no compile warnings or errors):
$ gcc -Wall -pthread test.c -o test
Here is the output:
$ ./test
1 2 3 4 5 6 7 8 9 10
Segmentation fault (core dumped)
And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
void *fillArray(int *size) {
int i;
for (i = 0; i < *size; i++) {
array[i] = i+1;
}
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
rc = pthread_create(&thread, NULL, fillArray(&size), &res);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Any ideas what could be the cause?
This doesn't compile for me: It fails with
dummy.cpp: In function ‘int main(int, char**)’:
dummy.cpp:29: error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
dummy.cpp:29: error: initializing argument 3 of ‘int pthread_create(_opaque_pthread_t**, const pthread_attr_t*, void* (*)(void*), void*)’
Which is because you're actually calling fillArray and passing its result to pthread_create, rather than passing the function pointer. I expect your code will need to look more like this (UNTESTED!) : (Note I changed signature of fillArray, created data struct type to pass to fillArray, changed how pthread_create is called)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
struct fillArrayData {
int * array;
int size;
int * result;
};
void *fillArray(void *void_data) {
fillArrayData * data = (fillArray*)void_data;
for (int i = 0; i < data.size; i++) {
data.array[i] = i+1;
}
//You could fill in some return info into data.result here if you wanted.
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
fillArrayData data;
data.array = array;
data.size = 10;
rc = pthread_create(&thread, NULL, fillArray, &data);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Error in
Calling function pointer
passing parameter to thread handler
In pthread prototype of pthread_create below
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
1st argument - pthread_variable
2nd argument - thread attrubutes
3rd argument - thread handler(function pointer name)
4th argument - variable need to pass thread handler.
In 4th argument - if two thread want to share single variable, then create global variable, and the pass this variable when creating thread.
sample program:
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
further details here
The problem is in following:
I want to write a short program that creates 10 threads and each prints a tread "id" that is passed to thread function by pointer.
Full code of the program is below:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct params {
pthread_mutex_t mutex;
int id;
};
typedef struct params params_t;
void* hello(void* arg){
int id;
pthread_mutex_lock(&(*(params_t*)(arg)).mutex);
id = (*(params_t*)(arg)).id;
pthread_mutex_unlock(&(*(params_t*)(arg)).mutex);
printf("Hello from %d\n", id);
}
int main() {
pthread_t threads[10];
params_t params;
pthread_mutex_init (¶ms.mutex , NULL);
int i;
for(i = 0; i < 10; i++) {
params.id = i;
if(pthread_create(&threads[i], NULL, hello, ¶ms));
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
The supposed output is (not necessary in this order):
Hello from 0
....
Hello from 9
Actual result is:
Hello from 2
Hello from 3
Hello from 3
Hello from 4
Hello from 5
Hello from 6
Hello from 8
Hello from 9
Hello from 9
Hello from 9
I tried to place mutex in different places in hello() function, but it didn't help.
How should I implement thread sync?
EDIT: Supposed result is not necessary 0...9 it can be any combination of these numbers, but each one should appear only one time.
The problem lies in the below code:
for(i = 0; i < 10; i++)
{
params.id = i;
if(pthread_create(&threads[i], NULL, hello, ¶ms));
}
Your params.id value keeps getting updated in the main thread, whereas you are passing the same pointer to all the threads.
Please create seperate memory for params by dynamically allocating it and pass it to different threads to solve the problem.
EDIT1:
Your usage of mutex to protect is also an incorrect idea. Though your mutex if used in main while setting the id also, may make the updation mutually exclusive, but you may not get your desired output. Instead of getting values from 0 .. 9 in different threads, you may get all 9s or still multiple threads may print same values.
So, using thread synchronization is not such a good idea for the output which you are expecting. If you still need to use one param variable between all threads and get output as 0 to 9 from each of the threads, better move the pthread_join into the first loop. This will ensure that each thread gets created, prints the value and then returns before the main spawns the next thread. In this case, you don't need the mutex also.
EDIT2:
As for the updated question, where it is asked that it is not necessary to print the numbers 0..9 in a sequence, the printing can be random, but only once, the problem still remains the same more or less.
Now, let's say, the value of params.id is first 0 and thread 0 got created, now, thread 0 must print it before it is updated in the main thread, else, when thread 0 accessess it, the value of params.id would have become 1 and you will never get your unique set of values. So, how to ensure that thread 0 prints it before it is updated in main, Two ways for it:
Ensure thread 0 completes execution and printing before main updates
the value
Use condition variables & signalling to ensure that main thread waits
for thread 0 to complete printing before it updates the value (Refer
to Arjun's answer below for more details)
In my honest opinion, you have selected the wrong problem for learning synchronization & shared memory. You can try this with some good problems like "Producer-Consumer", where you really need synchronization for things to work.
There are two problems:
A. You're using a lock but main is unaware of this lock.
B. A lock is not enough in this case. What you would want is for threads to cooperate by signalling each other (because you want main to not increment the variable until a thread says that it is done printing it). You can use a pthread_cond_t to achieve this (Look here to learn more about this). This boils down to the following code (basically, I added an appropriate usage of pthread_cond_t to your code, and a bunch of comments explaining what is going on):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct params {
pthread_mutex_t mutex;
pthread_cond_t done;
int id;
};
typedef struct params params_t;
void* hello(void* arg){
int id;
/* Lock. */
pthread_mutex_lock(&(*(params_t*)(arg)).mutex);
/* Work. */
id = (*(params_t*)(arg)).id;
printf("Hello from %d\n", id);
/* Unlock and signal completion. */
pthread_mutex_unlock(&(*(params_t*)(arg)).mutex);
pthread_cond_signal (&(*(params_t*)(arg)).done);
/* After signalling `main`, the thread could actually
go on to do more work in parallel. */
}
int main() {
pthread_t threads[10];
params_t params;
pthread_mutex_init (¶ms.mutex , NULL);
pthread_cond_init (¶ms.done, NULL);
/* Obtain a lock on the parameter. */
pthread_mutex_lock (¶ms.mutex);
int i;
for(i = 0; i < 10; i++) {
/* Change the parameter (I own it). */
params.id = i;
/* Spawn a thread. */
pthread_create(&threads[i], NULL, hello, ¶ms);
/* Give up the lock, wait till thread is 'done',
then reacquire the lock. */
pthread_cond_wait (¶ms.done, ¶ms.mutex);
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
}
/* Destroy all synchronization primitives. */
pthread_mutex_destroy (¶ms.mutex);
pthread_cond_destroy (¶ms.done);
return 0;
}
I see that the example you are trying is a toy program to probably learn about the POSIX thread library. In the real world, as we all know this can be done much faster without even using threads. But you already know this.
The problem is that you are modifying the params.id "unprotected" in main. This modification in main also needs to be mutex protected. You could protect this access by localizing this by creating getId() and setId() functions that would lock the mutex and protect access to the id, as follows. This will most likely still give the problem reported, since depending on when the thread calls getData() it will have one value or another. So to solve this, you could add an incrementId() function and call it from the hello() function.
struct params {
pthread_mutex_t mutex;
int id;
};
typedef struct params params_t;
int getId(params_t *p)
{
int id;
pthread_mutex_lock(&(p->mutex));
id = p->id;
pthread_mutex_unlock(&(p->mutex));
return id;
}
void setId(params_t *p, int val)
{
pthread_mutex_lock(&(p->mutex));
p->id = val;
pthread_mutex_unlock(&(p->mutex));
}
void incrementId(params_t *p)
{
pthread_mutex_lock(&(p->mutex));
p->id++;
pthread_mutex_unlock(&(p->mutex));
}
void* hello(void* arg){
params_t *p = (params_t*)(arg);
incrementId(p);
int id = getId(p);
// This could possibly be quite messy since it
// could print the data for multiple threads at once
printf("Hello from %d\n", id);
}
int main() {
pthread_t threads[10];
params_t params;
params.id = 0;
pthread_mutex_init (¶ms.mutex , NULL);
int i;
for(i = 0; i < 10; i++) {
if(pthread_create(&threads[i], NULL, hello, ¶ms));
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
A better way to get a unique thread id would be to define the hello method as follows:
void* hello(void* arg){
pthread_t threadId = pthread_self();
printf("Hello from %d\n", threadId);
}
And to avoid the problem with all threads trying to print at once, you could do the following:
void* hello(void* arg){
params_t *p = (params_t*)(arg);
pthread_mutex_lock(&(p->mutex));
p->id++;
int id = p->id;
printf("Hello from %d\n", id);
pthread_mutex_unlock(&(p->mutex));
}
Easiest way to get the desired output would be to modify your main function as follows:
int main() {
pthread_t threads[10];
params_t params;
pthread_mutex_init (¶ms.mutex , NULL);
int i;
for(i = 0; i < 10; i++) {
params.id = i;
if(pthread_create(&threads[i], NULL, hello, ¶ms));
pthread_join(threads[i], NULL); //wait for thread to finish
}
/*for(i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
}*/
return 0;
}
Output would be:
Hello from 0
...
Hello from 9
EDIT: Here's the synchronization for the corrected question:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct params {
pthread_mutex_t* mutex;
int id;
};
typedef struct params params_t;
void* hello(void* arg){
int id = 0;
params_t* params = (params_t*)arg;
if(params != 0)
{
id = params->id;
delete params;
params = 0;
}
printf("Hello from %d\n", id);
}
int main() {
pthread_t threads[10];
params_t* params = 0;
pthread_mutex_t main_mutex;
pthread_mutex_init (&main_mutex , NULL);
int i;
for(i = 0; i < 10; i++) {
params = new params_t(); //create copy of the id to pass to each thread -> each thread will have it's own copy of the id
params->id = i;
params->mutex = &main_mutex;
if(pthread_create(&threads[i], NULL, hello, params));
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
Each thread must have it's own copy of the id so that the other threads do not modify the id before it is printed.
I'm just putting this one here to provide another solution to this problem - this one does not involve mutexes - no synchronization - no conditionals, etc.
The main dfference is that we are using pthread_detach to automatically release the thread's resources upon completion.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUMTHREADS 10
typedef struct params {
int id;
} params_t;
void* hello(void *arg)
{
params_t *p = (params_t*)arg;
int status;
status = pthread_detach(pthread_self());
if (status !=0 )
{
printf("detaching thread\n");
abort();
}
printf("Hello from %d\n", p->id);
free(p);
return NULL;
}
int main()
{
pthread_t thread;
params_t *par;
int i, status;
for (i=0; i<NUMTHREADS; i++)
{
par = (params_t*)malloc(sizeof(params_t));
if (par == NULL)
{
printf("allocating params_t");
abort();
}
par->id = i;
status = pthread_create(&thread, NULL, hello, par);
if (status != 0)
exit(1);
}
/* DO some more work ...*/
sleep(3);
exit(0);
}