I'm brand new to pthreads, and I'm trying to understand what can be done to avoid problems when using simultaneous threads to write to the same global variables. Here's the simplest possible example:
pthread_t tid1, tid2 ;
int sum = 0 ;
void process()
{
for (int i ; i<100; i++)
sum += 1 ;
}
int main()
{
pthread_create(&tid1, NULL, (void *) process, NULL ) ;
pthread_create(&tid2, NULL, (void *) process, NULL ) ;
pthread_join(tid1, NULL) ;
pthread_join(tid2, NULL) ;
printf("Sum = %d\n", sum) ;
}
When I execute this code, it sometimes prints 200 and sometimes prints 100, implying in the latter case, I assume, that both threads were trying to write to 'sum' at exactly the same time, and one thread got blocked.
In my real world application, 'sum' might be a large array, and one thread might be trying to update one element while another is usually trying to update a different element of the same array.
What is the simplest/cleanest way to ensure that all intended read/write operations on a global variable or array succeed or at least to verify whether the operation succceeded? It isn't necessary to preserve the order of operation.
I seem to have found an answer -- I had not previously known about mutex until it was mentioned in response to a different question:
pthread_t tid1, tid2 ;
pthread_mutex_t lock;
int sum = 0 ;
void process()
{
for (int i ; i<100; i++) {
pthread_mutex_lock(&lock);
sum += 1 ;
pthread_mutex_unlock(&lock);
}
}
int main()
{
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}
pthread_create(&tid1, NULL, (void *) process, NULL ) ;
pthread_create(&tid2, NULL, (void *) process, NULL ) ;
pthread_join(tid1, NULL) ;
pthread_join(tid2, NULL) ;
pthread_mutex_destroy(&lock);
printf("Sum = %d\n", sum) ;
}
Related
I wanted to make a program that writes the odd and even numbers between 1 and 100 with 2 functions , the first function prints the first 5 odd numbers , the second function prints the first 5 even numbers and again we return to the first function to print the second 5 odd numbers and so on .
In this program i wanted to alternate between only 2 threads , but i can't find the solution . Here's my code , in this code i created 40 threads.Does anyone knows how to alternate between 2 threads and find the same output.
#include<stdio.h>
#include<pthread.h>
pthread_t tid[40];
int pair=2;
int impair=1 ;
pthread_mutex_t lock;
void* genpair(void *arg)
{
pthread_mutex_lock(&lock);
int i = 0;
for (i=0 ; i<5 ; i++,pair+=2)
{
printf("%d ",pair) ;
}
printf(" ");
pthread_mutex_unlock(&lock);
return NULL;
}
void* genimpair(void *arg)
{
pthread_mutex_lock(&lock);
int i = 0;
for (i=0 ; i<5 ; i++,impair+=2)
{
printf("%d ",impair) ;
}
printf(" ");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(void)
{
int i = 0;
int j=0 ;
int err;
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}
for(j=0 ; j<20 ; j+=2)
{
pthread_create(&(tid[j]), NULL, &genpair, NULL);
pthread_create(&(tid[j+1]), NULL, &genimpair, NULL);
pthread_join(tid[j], NULL);
pthread_join(tid[j+1], NULL);
}
pthread_mutex_destroy(&lock);
return 0;
}
You cannot ensure which thread will be able to pass before the other with mutexes only. A mutex is there only to ensure that only one thread will be able to run the critical code. You can use a conditional variable associated to your mutex to make them pass one after the other, as in the following pseudo code:
// thread1
do {
lock(m);
while (turn==0) cond_wait(m); // release the key if not my turn, retry until my turn
do my job;
turn = 0; // give hand to the other
cond_broadcast(m); // awake threads waiting for key (blocked in lock or cond_wait)
unlock(m); // release the lock
} while ();
// thread2
do {
lock(m);
while (turn==1) cond_wait(m);
do my job;
turn = 1;
cond_broadcast(m);
unlock(m);
} while();
You can also use two semaphores for the same job...
You must use 2 different mutex and your code be like this
//Thread pair
{
pthread_mutex_lock(&pairLock)
//Do pair job
pthread_mutex_unlock(&impairLock)
}
//Threa impair
{
pthread_mutex_lock(&impairLock)
//Do impair job
pthread_mutex_unlock(&pairLock)
}
The mutex of the starting thread must start at 1 (unlocked) and the other one at 0 (locked)
Edit: Using the same mutex for all your threads makes that only one thread can do it's job but doesn't force any order or alternance (Depends on system scheduler). In your case genimpair could execute first if scheduler says so, but it won't be interrupted by genpair, in the next loop it could be same order or not
I'm trying to make a simple program using pthreads, want to make 6 threads and pass index to all of them. here's the code:
#include <pthread.h>
#include <stdio.h>
#define num_students 6
void thread_starter();
int main() {
pthread_t thread1[num_students];
int i = 0;
for(i = 0; i<num_students; i++) {
int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
}
sleep(1);
}
void thread_starter(void* a) {
printf("Thread %i \n", *((int*)a));
}
And the output:
Thread 2
Thread 3
Thread 2
Thread 4
Thread 5
Thread 5
why do they have commmon names? what's wrong?
Thanks
You're passing a stack address from the main thread into all the child threads. There is no guarantee when these threads will be scheduled so you have no way of knowing whether the main thread will have updated its stack variable by the time each child gets around to reading it.
To avoid this, you need to allocate memory for the data being passed to each thread.
The easiest way to do this in your example is to use another automatic variable to store the data being passed to the new threads
void thread_starter(void* a);
int main() {
pthread_t thread1[num_students];
int thread_data[num_students];
int i = 0;
for(i = 0; i<num_students; i++) {
thread_data[i] = i;
pthread_create(&thread1[i], NULL, thread_starter, &thread_data[i]);
}
sleep(1);
}
Note also that you can avoid having to cast thread_starter if you give it the correct signature in your forward declaration.
For more complex programs you may need to dynamically allocate memory for each thread instead, passing ownership of that memory to the new threads.
int main() {
pthread_t thread1[num_students];
int i = 0;
for(i = 0; i<num_students; i++) {
int* data = malloc(sizeof(*data));
*data = i;
pthread_create(&thread1[i], NULL, thread_starter, data);
}
sleep(1);
}
void thread_starter(void* a) {
printf("Thread %i \n", *((int*)a));
free(a);
}
Finally, using sleep(1) isn't a very rigorous way of ensuring that all your threads will be run. It'd be better to use pthread_join instead
for(i = 0; i<num_students; i++) {
pthread_join(thread1[i], NULL);
}
sleep is not the correct tool to wait for spawned threads, use pthread_join for this.
Your main function terminating is equivalent to calling exit for the whole program and killing all the other threads.
Try This for Variation
void thread_starter(void* a) {
// Put a sleep(1) Here and see you will get even bizarre results
printf("Thread %i \n", *((int*)a));
}
Ok the problem here is of course
the race condition at this point here
int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
lets say the first thread is created and the value at q is 0
now assume that before executing the statement Here
printf("Thread %i \n", *((int*)a));
if the main thread loops further and executes this statement here
int q = i;
again, then the q value changes (because its a reference) hence the problem
well one way to avoid this is to copy this reference variable in a local variable in thread routine also use mutex.
Sorry I was on a Hurry some more tips from my side
#define num_students 6
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // A Global Mutex
Will aquire a lock Here
pthread_mutex_lock( &mutex );
printf("\n Got Mutex %d\n", i);
int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
and will release the lock Here in child Routine
int i = *((int*)a);
sleep(1);
pthread_mutex_unlock( &mutex );
printf("Thread %i \n", i);
P.S - Remove un necessary Prints and Sleeps where ever not applicable
Basic function of my program: create number of counters (0), create number of instructions per threads, create the struct instructions which contain counter*, repetitions and work_fn (increment, decrement etc).
Program will build all the dynamic structure (already coded up)
then spawn threads and join. One thread can have more than one instructions.
static void* worker_thread(void *arg){
long long *n;
pthread_mutex_lock( &lock1 );
n = (long long *) arg;
printf("Testing: %lld.\n", n);
pthread_mutex_unlock( &lock1 );
return NULL;
}
//nthreads is the total number of threads
for(int i=0; i < nthreads ; i++){
pthread_create( &thread_id[i], NULL, worker_thread, &i); //Problem
}
for(int i=0; i < nthreads ; i++){
pthread_join( thread_id[i], NULL);
}
I am trying to test the thread function, firstly create number of threads then join them.
But I can't seems to pass the current thread number [i] in my case to the worker thread function.
Use
(void *) i
in pthread_create
and then
int i = (int) arg
int n = (int)arg;
In your worker_thread function.
And
(void*)i
Instead of &i in your thread spawn
I'm trying to write a multi-threaded program, the number of threads based on command-line input, and so I can't hard-code pre-declared threads. Is this a valid way of doing it?
int threads = 5; // (dynamic, not hard-coded)
int i = 0;
pthread_t * thread = malloc(sizeof(pthread_t)*threads);
for (i = 0; i < threads; i++) {
pthread_t foobar;
thread[i] = foobar; // will this cause a conflict?
}
for (i = 0; i < threads; i++) {
int ret = pthread_create(&thread[i], NULL, (void *)&foobar_function, NULL);
if(ret != 0) {
printf ("Create pthread error!\n");
exit (1);
}
}
Here's my result from modifications suggested below. Seems to work just fine.
int threads = 5;
int i;
pthread_t * thread = malloc(sizeof(pthread_t)*threads);
for (i = 0; i < threads; i++) {
int ret = pthread_create(&thread[i], NULL, &foobar_function, NULL);
if(ret != 0) {
printf ("Create pthread error!\n");
exit (1);
}
// pthread_join(thread[i], NULL); // don't actually want this here :)
}
sleep(1); // main() will probably finish before your threads do,
free(thread); // so we'll sleep for illustrative purposes
What's in the first cycle? Does it set the array elements to uninitialized value?
So i think that's what you need:
int threads = 5, i = 0, ret = -1;
pthread_t * thread = malloc(sizeof(pthread_t)*threads);
for (i = 0; i < threads; i++) {
ret = pthread_create(&thread[i], NULL, &foobar_function, NULL);
if(ret != 0) {
printf ("Create pthread error!\n");
exit (1);
}
}
It spawns threads threads, starting foobar_function in each. And you have (if everything goes well:)) their ids in thread array. So for example you can cancel second thread by calling pthread_cancel(thread[1]) etc.
The first for loop is not valid C, and I'm not sure what you want it to do. Just remove it and the rest of the code looks ok, aside from the incorrect cast on foobar_function. The cast should be:
(void *(*)(void *))foobar_function
but unless the type is already this, or something very close, your program probably has undefined behavior. It would be better to fix the function signature so no cast is needed.
If you're trying to write a multithreaded program, but don't understand how to allocate a dynamically sized data structure, you may be doing things wrong.
Learn to walk before you run.
Consider using an easier language, and avoiding the use of (explicit) threads.
Threads are very difficult to use correctly; dynamically sized arrays are very easy to achieve (even fairly easy in C)
In my main function, I spawn j threads which all compute the same task in parallel -- and then I want to wait for them to finish before exiting.
int main(...) {
// ...
int threads = 6;
pthread_t* thread = malloc(sizeof(pthread_t)*threads);
for(i = 0; i < threads; i++) {
struct thread_param *tp;
tp = malloc(sizeof(*tp));
// ...
int ret = pthread_create(&thread[i], NULL, &control, (void*)tp);
if(ret != 0) {
printf ("Create pthread error!\n");
exit (1);
}
}
for (j = 0; j < threads; j++) {
printf("JOINING THREAD: %i\n", j);
pthread_join( &thread[j], NULL);
}
exit(0);
}
However, nothing waits. Main just exits without ever completing the threaded tasks. Am I missing something?
hey, try pthread_join( thread[j], NULL); i think the problem is with types. I checked docs:
int pthread_join(pthread_t thread, void **value_ptr);
and thread is p_thread*, and thread[j] is p_thread, while &thread[j] is p_thread*, which is invalid. There just might internal error happen.
Edit: Yeah, I am very positive with that, pthread_t is basically int, so pthread_t* is accepted, it is just invalid thread handle, so pthread_join fails internally.