C pthread allow only four threads to execute function - c

Here is a problem, say I need to execute a function x times which does some taks, but only four threads can be executing it at any given time. So thread A,B,C,D can start task 0,1,2,3 respectively. However, task four can't start until one of the threads completed, so say if thread A completes, then the next task can be executed by one of the free threads. This should repeat x times, where x is the number of times the function needs to be called.
So I've used semaphores and join the pthread after it completes to ensure it completes. However, sometimes the main function finishes executing before some of the threads complete, and valgrind is complaining that my pthread_create is leaking memory. I think the way I'm doing is incorrect or is a naive approach, so any guidance or example code to fix this will be most appreciated! Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
sem_t s;
typedef struct Data Data;
struct Data {
pthread_t* a;
int index;
int j;
};
void* someFunction(void* arg){
/* Only at most num_threads should be here at once; */
sem_wait(&s);
Data* d = arg;
printf("Successfully completed task %d with thread %d\n", d->index, d->j);
sleep(2);
pthread_t* z = d->a;
free(d);
pthread_join(*z, NULL);
sem_post(&s);
return 0;
}
int main(void){
int num_task = 15; // i need to call someFunction() 9000 times
int num_threads = 4;
int j = 0;
sem_init(&s, 0, num_threads);
pthread_t thread_ids[num_threads];
for (int i = 0; i < num_task; i ++){
/*NEED TO COMPLETE num_tasks using four threads;
4 threads can run someFunction() at the same time; so one all four are currently executing someFunction(), other threads can't enter until one has completed. */
if (j == num_threads){
j = 0; // j goes 0 1 2 3 0 1 2 3 ...
}
Data* a = malloc(sizeof(Data));
a->a = thread_ids + j;
a->index = i;
a->j = j;
sem_wait(&s);
pthread_create(thread_ids + j, NULL, someFunction, a);
sem_post(&s);
j ++;
}
return 0;
}
Thank you so much

Having threads wait for each other usually gets messy quickly, and you're likely to end up in situations where a thread tries to join itself, or is never joined.
The most reliable way to have at most four threads running is to only create four threads.
Instead of creating threads as needed, you let each thread (potentially) perform more than one task.
You can separate the "task" concept from the "thread" concept:
Make a queue of tasks for the threads to perform.
Create four threads.
Each thread takes a task from the queue and performs it, repeating until the queue is empty.
Wait for the threads to finish in main.
The only thing that needs synchronising is the removal of a task from the queue, which is very simple.
(If the tasks are not independent, you need more complex plumbing.)
Pseudocode (I have invented some names as I'm not overly familiar with pthreads):
typedef struct Task
{
/* whatever */
};
/* Very simplistic queue structure. */
typedef struct Queue
{
mutex lock;
int head;
Task tasks[num_tasks];
};
/* Return front of queue; NULL if empty. */
Task* dequeue(Queue* q)
{
Task* t = NULL;
lock_mutex(q->lock);
if (q->head < num_tasks)
{
t = &q->tasks[q->head];
q->head++;
}
unlock_mutex(q->lock);
return t;
}
/* The thread function is completely unaware of any multithreading
and can be used in a single-threaded program while debugging. */
void* process(void* arg)
{
Queue* queue = (Queue*) arg;
for (;;)
{
Task* t = dequeue(queue);
if (!t)
{
/* Done. */
return NULL;
}
/* Perform task t */
}
}
/* main is very simple - set up tasks, launch threads, wait for threads.
No signalling, no memory allocation. */
int main(void)
{
pthread threads[num_threads];
Queue q;
q.head = 0;
/* Fill in q.tasks... */
/* Initialise q.lock... */
for (int ti = 0; ti < num_threads; ti++)
{
pthread_create(threads + ti, NULL, process, &q);
}
for (int ti = 0; ti < num_threads; ti++)
{
/* join the thread */
}
return 0;
}

Your code starts four threads at a time and waits until they are finished. However, your main loop only creates the threads, it does not for them to exit.
After you created a thread your OS will schedul it whenever it wants.
That means you have to join the last four threads you created after your for loop. So they have a chance to finish their work and free their memory.
Regards

Related

How to implement and profile pthreads continuously created on the heap?

Introduction
I have a program where child threads are created that I would like to profile with Valgrind memcheck. From the responses to a previous question I've asked, I will need to use joinable (rather than detached) threads in order to test and profile reliably with Valgrind memcheck.
Stack vs. Heap Allocation
My program is sufficiently large where I don't think I can create the thread and join it in the same scope. For this reason I allocate space for the pthread_t on the heap.
Attempt #1 - Joining Immediately
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
void my_thread() {
printf("I'm in a child thread!\n");
pthread_exit(NULL);
}
pthread_t* const make_thread() {
pthread* const thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, (void*) &my_thread, NULL));
return thread;
}
int main() {
printf("Hello, world!\n");
uint8_t i;
for(i = 0; i < 255; ++i) {
pthread_t* const thread_handle = make_thread();
pthread_join(*thread_handle, NULL);
free(thread_handle);
}
return 0;
}
This seems to make sense, but now I want to extend this example by not joining the thread immediately, and only joining on program exit (say, because these threads may become long-living). IOW the above example kind of defeats the purpose of multithreading.
I want to create threads and only really ever force a join on program exit.
Attempt #2 - Joining at the end
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
#include <glib-2.0/glib.h>
#include <unistd.h>
void my_thread() {
sleep(3);
printf("I'm in a child thread!\n");
pthread_exit(NULL);
}
pthread_t* const make_thread() {
pthread* const thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, (void*) &my_thread, NULL));
return thread;
}
int main() {
printf("Hello, world!\n");
GArray* const thread_handles = g_array_new(TRUE, TRUE, sizeof(pthread*));
// Important loop
uint8_t i;
for(i = 0; i < 255; ++i) {
pthread_t* const thread_handle = make_thread();
g_array_append_val(thread_handles, thread_handle);
}
for(i = 0; i < thread_handles->len; ++i) {
pthread_t* const thread_handle =
g_array_index(thread_handles, pthread*, i);
pthread_join(*thread_handle, NULL);
free(thread_handle);
}
g_array_free(thread_handles, TRUE);
return 0;
}
This is cool but what if "Important loop" is actually endless? How can I prevent thread_handles from expanding until it takes up all available memory?
In the actual program (these are just minimal examples), the program receives network messages and then kicks off threads for some special types on network messages.
So, what is your real issue?
For normal network servers, etc, the usual is to combine both of your approaches.
The main thread has a two nested loops that:
waits for a connection/message.
Creates a thread.
Adds this to the list of active threads.
Loops on all active threads in the list (as below)
Loop on the active thread list:
look for a thread that is marked "done"
Remove it from the list
join it
free the thread struct
The above works pretty much the same if the thread control structs are allocated (via malloc) or come from a fixed, pre-defined array of structs [which can be function scoped to main or global/static scope].
Here's some C-like pseudo code to illustrate:
// task control
typedef struct tsk {
pthread_t tsk_tid; // thread id
int tsk_sock; // socket/message struct/whatever
int tsk_isdone; // 1=done
} tsk_t;
void
my_thread(tsk_t *tsk)
{
// do stuff ...
// tell main we're done
tsk->tsk_isdone = 1;
return (void *) 0;
}
void
main_loop(void)
{
while (1) {
// wait for connection, message, whatever ...
int sock = accept();
// create thread to handle request
tsk_t *tsk = make_thread(sock);
// enqueue it to list of active threads
list_enqueue(active_list,tsk);
// join all completed threads
while (1) {
int doneflg = 0;
// look for completed threads
for_all(tsk,active_list) {
if (! tsk->tsk_isdone)
continue;
// remove task from queue/list
list_remove(active_list,tsk);
// join the thread
pthread_join(tsk->tsk_tid,NULL)
// release storage
free(tsk);
// say we reaped/joined at least one thread
doneflg = 1;
}
// stop when we've joined as many threads as we can
if (! doneflg)
break;
}
}
}
Note that while creating a new thread for a new connection may be reasonable, doing so for messages from a given connection can be very slow.
It may be better to have a pool of worker threads. See my answer: Relative merits between one thread per client and queuing thread models for a threaded server?

pthread in C : i can't figure why pthread_cond_signal is not waking up one thread

I want a routine to be done by multiple threads, once they are created they need their work to be all finished before copying their calculated things. So a thread is on cond_wait once it has its work done.
A piece of code that works now:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_RAYCAST_THREADS 2
typedef struct s_thread_env
{
int id;
pthread_t thread;
int work_done;
void *shared_data;
} t_thread_env;
typedef struct s_shared_data
{
t_thread_env *tab_thread_env;
int max_thread;
int all_work_done;
pthread_mutex_t mutex;
pthread_cond_t cond;
int stop;
} t_shared_data;
void set_threads_again(int id, t_shared_data *shared_data)
{
int i;
shared_data->all_work_done = 0;
i = -1;
while (++i < shared_data->max_thread)
shared_data->tab_thread_env[i].work_done = 0;
//i = -1;
//while (++i < shared_data->max_thread)
//{
//if (i != id)
//{
//printf("cond_signal to thread %i\n", i);
//pthread_cond_signal(&shared_data->cond);
//}
//}
pthread_cond_broadcast(&shared_data->cond);
}
void wait_or_signal(t_thread_env *thread_env, t_shared_data *shared_data)
{
int i;
i = 0;
while (i < shared_data->max_thread && shared_data->tab_thread_env[i].work_done)
i++;
if (i == shared_data->max_thread)
{
printf(" allworkdone sent by thread %i\n", thread_env->id);
//printf(" copy_screenpixels() by thread %i\n", thread_env->id);
set_threads_again(thread_env->id, shared_data);
}
else
{
printf(" thread number %i is waiting for other threads\n", thread_env->id);
pthread_cond_wait(&shared_data->cond, &shared_data->mutex);
printf("ENFIN ! thread number %i woke up from condwait\n", thread_env->id);
}
}
void *routine(void *arg)
{
t_thread_env *thread_env;
t_shared_data *shared_data;
int stop;
thread_env = (t_thread_env *)arg;
shared_data = (t_shared_data *)thread_env->shared_data;
pthread_mutex_lock(&shared_data->mutex);
while (!shared_data->stop)
{
printf("new frame> thread_id = %i, thread_env->work_done = %i\n", thread_env->id, thread_env->work_done);
pthread_mutex_unlock(&shared_data->mutex);
printf(" raycast() in routine thread %i\n", thread_env->id);
pthread_mutex_lock(&shared_data->mutex);
thread_env->work_done++;
wait_or_signal(thread_env, shared_data);
}
pthread_mutex_unlock(&shared_data->mutex);
return (0);
}
void init_thread_env(t_shared_data *shared_data, int i)
{
t_thread_env *thread_env;
thread_env = &shared_data->tab_thread_env[i];
thread_env->id = i;
thread_env->shared_data = shared_data;
if (pthread_create(&thread_env->thread, NULL, routine, thread_env) != 0)
printf("Error pthread_create for %i\n", i);
}
void free_all(t_shared_data *shared_data)
{
int i;
pthread_mutex_lock(&shared_data->mutex);
shared_data->stop = 1;
pthread_mutex_unlock(&shared_data->mutex);
i = -1;
while (++i < shared_data->max_thread)
pthread_join(shared_data->tab_thread_env[i].thread, NULL);
printf("\nEND\n\n");
//free etc
}
int main()
{
int i;
t_shared_data *shared_data;
shared_data = (t_shared_data*)malloc(sizeof(t_shared_data)); // if (!shared data){free etc}
shared_data->max_thread = MAX_RAYCAST_THREADS;
pthread_mutex_init(&shared_data->mutex, 0);
pthread_cond_init(&shared_data->cond, 0);
shared_data->tab_thread_env = (t_thread_env*)malloc(sizeof(t_thread_env) * shared_data->max_thread);
i = -1;
while (++i < shared_data->max_thread)
init_thread_env(shared_data, i);
while (1)
sleep(1); //program is turning
free_all(shared_data);
return (0);
}
The correct output:
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
new frame> thread_id = 1, thread_env->work_done = 0
raycast() in routine thread 1
allworkdone sent by thread 1
cond_signal to thread 0
new frame> thread_id = 1, thread_env->work_done = 0
ENFIN ! thread number 0 woke up from condwait
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
raycast() in routine thread 1
allworkdone sent by thread 1
cond_signal to thread 0
new frame> thread_id = 1, thread_env->work_done = 0
ENFIN ! thread number 0 woke up from condwait
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
raycast() in routine thread 1
Thank you for reading me, have a good day!
EDIT: I made a more readable and compilable version with only 1 mutex (old version: https://pastebin.com/4zMyBJi2).
EDIT2: deleted some parts of the original post, and tried to avoid every data races, my code still has some (as it still does not work). But I think I am close to get something working
EDIT3: Ok it is working now, I edited the code. The main issue was my disastrous use of the shared_data variables.
I tried to make my raycasting threads work using 1 call of
pthread_create for each thread (in an initialisation function). Is
it possible to do it?
Each successful call to pthread_create creates exactly one thread, so this is the only way to do it. But do not get confused between threads' start functions and threads themselves. Multiple threads can be created to run the same thread function, but this requires multiple calls to pthread_create, one for each thread.
I guess it is better (for performances) to do
it in this way (rather than an enormous amount of pthread_create and
pthread_join calls), is this correct?
Having chosen to use a certain number of threads to do certain pieces of work, the number of pthread_create calls is already determined. If you have performance concerns then they should be about how many threads to use, the details of the work they are to perform, and the nature and granularity of their synchronization.
In order to make it happen, the last thread (number n) to finish his
job has to tell the other ones that every thread has finished, so
there is a pthread_cond_wait for the (n - 1) first threads, and the
last thread (number n) calls pthread_cond_signal for each (n - 1)
first ones. Each thread has his own mutex.
That seems a little overkill, even if you can make it technically correct. It doesn't make much sense to have a mutex per thread, because mutexes are useful only when different threads use the same one. It may make sense to have different mutexes for protecting different shared resources, however. You would probably want CVs for some of those, but not all of them.
This appears to be (at least one area) where your code is failing. Your threads are not properly synchronized because they all rely on different mutexes to protect the same resources. It's not clear to me whether it makes sense for your program to have any more than just one mutex, but I would start by reducing your usage to that.

Pthread signalling in C Linux

I am working with multi-threading in Linux using Pthread.
Thread1 waits for an IRQ from Driver by polling a character device file (my driver has ISR to catch IRQ from HW).
IRQ -----> Thread1 |-----> Thread2
|-----> Thread3
|-----> Thread4
Whenever Thread1 gets an IRQ, I want send a signal to Thread2, Thread3 and Thread4 to wake them up and then work.
Now, I am trying to use "pthread conditional variable" and "pthread mutex". But it seems that is not good approach.
What is efficient way for synchronization in this case? Please help.
Thank you very much.
As I understand it, your problem is that your child threads (Threads 2 through 4) don't always wake up exactly once for every IRQ that Thread1 receives -- in particular, it might be that an IRQ is received while the child threads are already awake and working on an earlier IRQ, and that causes them not to be awoken for the new IRQ.
If that's correct, then I think a simple solution is to use a counting semaphore for each child-thread, rather than a condition variable. A semaphore is a simple data structure that maintains an integer counter, and supplies two operations, wait/P and signal/V. wait/P decrements the counter, and if the counter's new value is negative, it blocks until the counter has become non-negative again. signal/V increments the counter, and in the case where the counter was negative before the increment, awakens a waiting thread (if one was blocked inside wait/P).
The effect of this is that in the case where your main thread gets multiple IRQs in quick succession, the semaphore will "remember" the multiple signal/V calls (as a positive integer value of the counter), and allow the worker-thread to call wait/P that-many times in the future without blocking. That way no signals are ever "forgotten".
Linux supplies a semaphore API (via sem_init(), etc), but it's designed for inter-process synchronization and is therefore a little bit heavy-weight for synchronizing threads within a single process. Fortunately, it's easy to implement your own semaphore using a pthreads mutex and condition-variable, as shown below.
Note that in this toy example, the main() thread is playing the part of Thread1, and it will pretend to have received an IRQ every time you press return in the terminal window. The child threads are playing the part of Threads2-4, and they will pretend to do one second's worth of "work" every time Thread1 signals them. In particular note that if you press return multiple times in quick succession, the child threads will always do that many "work units", even though they can only perform one work-unit per second.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
struct example_semaphore
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int count; // acccess to this is serialized by locking (mutex)
};
// Initializes the example_semaphore (to be called at startup)
void Init_example_semaphore(struct example_semaphore * s)
{
s->count = 0;
pthread_mutex_init(&s->mutex, NULL);
pthread_cond_init(&s->cond, NULL);
}
// V: Increments the example_semaphore's count by 1. If the pre-increment
// value was negative, wakes a process that was waiting on the
// example_semaphore
void Signal_example_semaphore(struct example_semaphore * s)
{
pthread_mutex_lock(&s->mutex);
if (s->count++ < 0) pthread_cond_signal(&s->cond);
pthread_mutex_unlock(&s->mutex);
}
// P: Decrements the example_semaphore's count by 1. If the new value of the
// example_semaphore is negative, blocks the caller until another thread calls
// Signal_example_semaphore()
void Wait_example_semaphore(struct example_semaphore * s)
{
pthread_mutex_lock(&s->mutex);
while(--s->count < 0)
{
pthread_cond_wait(&s->cond, &s->mutex);
if (s->count >= 0) break;
}
pthread_mutex_unlock(&s->mutex);
}
// This is the function that the worker-threads run
void * WorkerThreadFunc(void * arg)
{
int workUnit = 0;
struct example_semaphore * my_semaphore = (struct example_semaphore *) arg;
while(1)
{
Wait_example_semaphore(my_semaphore); // wait here until it's time to work
printf("Thread %p: just woke up and is working on work-unit #%i...\n", my_semaphore, workUnit++);
sleep(1); // actual work would happen here in a real program
}
}
static const int NUM_THREADS = 3;
int main(int argc, char ** argv)
{
struct example_semaphore semaphores[NUM_THREADS];
pthread_t worker_threads[NUM_THREADS];
// Setup semaphores and spawn worker threads
int i = 0;
for (i=0; i<NUM_THREADS; i++)
{
Init_example_semaphore(&semaphores[i]);
pthread_create(&worker_threads[i], NULL, WorkerThreadFunc, &semaphores[i]);
}
// Now we'll pretend to be receiving IRQs. We'll pretent to
// get one IRQ each time you press return.
while(1)
{
char buf[128];
fgets(buf, sizeof(buf), stdin);
printf("Main thread got IRQ, signalling child threads now!\n");
for (i=0; i<NUM_THREADS; i++) Signal_example_semaphore(&semaphores[i]);
}
}
I like jeremy's answer, but it does have some lacking in that the interrupt dispatcher needs to know how many semaphores to increment on each interrupt.
Also each increment is potentially a kernel call, so you have a lot of kernel calls for each interrupt.
An alternate is to understand how pthread_cond_broadcast() works. I have put an example below:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#ifndef NTHREAD
#define NTHREAD 5
#endif
pthread_mutex_t Lock;
pthread_cond_t CV;
int GlobalCount;
int Done;
#define X(y) do { if (y == -1) abort(); } while (0)
void *handler(void *x) {
unsigned icount;
X(pthread_mutex_lock(&Lock));
icount = 0;
while (!Done) {
if (icount < GlobalCount) {
X(pthread_mutex_unlock(&Lock));
icount++;
X(pthread_mutex_lock(&Lock));
} else {
X(pthread_cond_wait(&CV, &Lock));
}
}
X(pthread_mutex_unlock(&Lock));
return NULL;
}
int
main()
{
X(pthread_mutex_init(&Lock, NULL));
X(pthread_cond_init(&CV, NULL));
pthread_t id[NTHREAD];
int i;
for (i = 0; i < NTHREAD; i++) {
X(pthread_create(id+i, NULL, handler, NULL));
}
int c;
while ((c = getchar()) != EOF) {
X(pthread_mutex_lock(&Lock));
GlobalCount++;
X(pthread_mutex_unlock(&Lock));
X(pthread_cond_broadcast(&CV));
}
X(pthread_mutex_lock(&Lock));
Done = 1;
X(pthread_cond_broadcast(&CV));
X(pthread_mutex_unlock(&Lock));
for (i = 0; i < NTHREAD; i++) {
X(pthread_join(id[i], NULL));
}
return 0;
}

Initialize and Deinitialize only once with multiple threads without mutexes

I have two functions initialize() and deinitialize() and each function should run only once. The structure is something similar to:
int *x;
initialize()
{
x = malloc(sizeof(int) * 10);
}
deinitialize()
{
free(x);
}
How can I ensure that only the first thread calls initialize and only the last thread calls deinitialize.
Can this be achieve without the use of mutex?
UPDATE:
Sorry for the poor information. I am actually modifying a library that contains the functions initialize() and deinitialize(). I need to make these two functions thread-safe. The users might use multiple threads and might call these functions more than once. I cannot assume that the users will call exactly once to initialize and deinitialize functions. I can only assume is that if a thread calls initialize, it will call deinitialize at some point.
The users will be using pthread library to create their different threads.
I don't know what you want to achieve, the most easiest is:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
int *x;
int running;
void initialization(void)
{
x = malloc(sizeof(int) * 10);
puts("First thread init x");
}
void deinitialization(void)
{
free(x);
puts("Last thread reset x");
}
void *handler(void *data)
{
printf("Thread started\n");
while (running) {
do_work();
}
printf("Thread exit\n");
}
int main(void)
{
pthread_t threads[3];
initialization();
for (int i = 0; i < 3; i++)
pthread_create(&threads[i], NULL, &handler, NULL);
sleep(2);
running = 0;
for (int i = 0; i < 3; i++)
pthread_join(threads[i], NULL);
deinitialization();
return 0;
}
Here you can be sure that your have called init() and deinit() only once.
UPDATE
Another variant little bit complicated, but here you also can be sure that init() called only once. Thread with id 0 can be start after 1 in this case we should wait while *x is NULL.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX_THREADS 3
int *x;
int running;
int init;
struct thread_info
{
pthread_t thread;
int id;
int first_id;
int last_id;
};
void initialization(void)
{
x = malloc(sizeof(int) * 10);
puts("First thread init x");
init = 1;
}
void deinitialization(void)
{
free(x);
puts("Last thread reset x");
}
void *handler(void *data)
{
struct thread_info *tinfo = data;
printf("Thread started\n");
if (tinfo->id == 0)
initialization();
while (!init);
/* EMPTY BODY */
while (running) {
do_work();
}
printf("Thread exit\n");
}
int main(void)
{
struct thread_info threads[MAX_THREADS] =
{
[0 ... 2].id = -1,
[0 ... 2].first_id = 0,
[0 ... 2].last_id = (MAX_THREADS - 1)
};
for (int i = 0; i < 3; i++)
pthread_create(&threads[i].thread, NULL, &handler,
((threads[i].id = i), &(threads[i])));
sleep(2);
running = 0;
for (int i = 0; i < 3; i++)
pthread_join(threads[i].thread, NULL);
deinitialization();
return 0;
}
deinit() is a little bit tricky because your last thread can be exiting and free(x) while another thread is still running and maybe use it. So I leave it after all threads is exiting.
This is the point about concurrent programming. You can never make any assumptions about the order in which the threads execute.
The exact timing of when tasks in a concurrent system are executed depend on the scheduling, and tasks need not always be executed concurrently. For example, given two tasks, T1 and T2:
T1 may be executed and finished before T2 or vice versa (serial and
sequential)
T1 and T2 may be executed alternately (serial and concurrent)
T1 and T2 may be executed simultaneously at the same instant of time
(parallel and concurrent)

c - running 2 threads in parallel with a shared variable

Just a beginner to threads, I'm just doing a task which involves these 2 threads.
#include <stdio.h>
#include <pthread.h>
int count = 0;
void waitFor(unsigned int secs)
{
unsigned int retTime = time(0) + secs;
while(time(0) < retTime);
}
void func1(void * args)
{
printf("In func1 ...\n");
long i = 0;
while(1){
i++;
if(count == 1)
break;
}
printf("The total number counted is: %ld \n", i);
count = 0;
i = 0;
}
void func2(void * args)
{
printf("In func2 ...\n");
waitFor(3);
count = 1;
}
int main()
{
pthread_t th1, th2;
int j = 0;
while(j++ < 4){
printf("\nRound:\t%d\n", j);
pthread_create(&th1, NULL, (void*)func1,NULL);
pthread_create(&th2, NULL, (void*)func2, NULL);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
waitFor(3);
}
return 0;
}
I've read various references and to my understanding pthread_join() means that if there are 2 or more threads, then they will wait for one thread to finish its execution and then next one will start executing and so on.
But when i run this program, the moment pthread_join(th1) is executed, both threads are created and executed 'concurrently'. How is this happening?
Output:
Round: 1
In func2 ...
In func1 ...
The total number counted is: 897651254
Round: 2
In func1 ...
In func2 ...
The total number counted is: 1051386065
........
My goal is to run these 2 threads in parallel. For now, join seems to do this; or am I going wrong somewhere?
And I've read that using volatile is not preferred for threads in C. So is there any way I could use count as a signal from thread 2 to 1?
Quote:
my understanding pthread_join() means that if there are 2 or more threads, then they will wait for one thread to finish its execution and then next one will start executing and so on
That is incorrect. Join simply means that the process waits until the thread has terminated.
Quote:
the moment pthread_join(th1) is executed, both threads are created and executed 'concurrently'.
That is incorrect. The threads are created and start when calling pthread_create Note: By start I mean that they are ready to execute. However, it is the OS that decides when they actually get to execute so it may take some time before they execute.
To share count between two threads you can use a mutex.
int count = 0;
pthread_mutex_t lock;
When accessing count you must first lock the mutex, read/write the variable and unlock the mutex.
Example:
pthread_mutex_lock(&lock);
count = 1;
pthread_mutex_unlock(&lock);
Example:
long i = 0;
while(1)
{
... code not using count ....
pthread_mutex_lock(&lock);
if(count == 1)
{
pthread_mutex_unlock(&lock);
break;
}
pthread_mutex_unlock(&lock);
... code not using count ....
}
And in main you'll need to initialize the mutex like:
pthread_mutex_init(&lock,NULL);

Resources