Alternate between 2 threads - c

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

Related

why does Pthread Signal from main, hangs the code?

The requirement for the sample application creating using pthread is given below:
A single thread is created from main using Pthread
Inside thread, Mutex is locked, a counter counts the value and while loop is incremented, While is set to the max count of 10.
after while loop finishes, the mutex is unlocked.
The above requirement I have tried implementing using pthread
Code is shown below:
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
int samples = 10;
int count = 0;
struct example
{
int i;
int a;
};
void *inc_x(void *x_void_ptr)
{
pthread_mutex_lock(&count_mutex);
printf("Thread is locked \n");
while(count < samples)
{
printf("inside While loop \n");
struct example *E2_ptr;
E2_ptr = (struct example *)x_void_ptr;
printf("inside thread count = %d\n",count);
E2_ptr->a = count;
E2_ptr->i = (count + 1);
count ++;
//pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
pthread_mutex_unlock(&count_mutex);
printf ( "\n Test Successful for Thread\n");
pthread_exit(NULL);
}
int main()
{
int x = 100, y = 0,i = 0;
struct example *E1_ptr;
E1_ptr->a = 0;
E1_ptr->i = 0;
printf("Before\t E1_ptr->a = %d\t, E1_ptr->i = %d\n",E1_ptr->a,E1_ptr->i);
pthread_t inc_x_thread;
if(pthread_create(&inc_x_thread, NULL, inc_x, E1_ptr))
{
printf("Error creating thread\n");
}
if(pthread_join(inc_x_thread, NULL))
{
printf("Error joining thread\n");
}
for(i = 0; i<(samples-1); i++)
{
if(pthread_cond_signal(&count_threshold_cv))
{
printf("Error Signaling thread at sample = %d\n",i);
}
}
printf("after\t E1_ptr->a = %d\t, E1_ptr->i = %d\n",E1_ptr->a,E1_ptr->i);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit (NULL);
return 0;
}
Doubt:
In the above code, the thread executes its function properly and exits.
Once the condition is applied, i.e. the below shown code is uncommented then,
pthread_cond_wait(&count_threshold_cv, &count_mutex);
Then the thread is stopped after 1st iteration of while loop as expected.
The signal is generated from main by the code shown below:
for(i = 0; i<(samples-1); i++)
{
if(pthread_cond_signal(&count_threshold_cv))
{
printf("Error Signaling thread at sample = %d\n",i);
}
}
observed that the signal is never sent.
Can someone please guide me, where am I going wrong. I'm a newbie to Pthreads.
Thanks in advance.
count_mutex and count_threshold_cv are not initialized, add:
int main()
{
pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init(&count_threshold_cv, NULL);
//...
E1_ptr is not initialized.
There are many ways to solve it:
You can call malloc to allocate memory:
struct example *E1_ptr = malloc(sizeof(struct example));
E1_ptr->a = 0;
E1_ptr->i = 0;
or holds pointer to local variable:
struct example ex;
struct example *E1_ptr = &ex; //malloc(sizeof(struct example));
E1_ptr->a = 0;
E1_ptr->i = 0;
or
struct example ex;
ex.a = 0;
ex.i = 0;
then create thread with pthread_create(&inc_x_thread, NULL, inc_x, &ex)
pthread_cond_signal function does not wait. If a thread is blocked by condition variable pthread_cond_signal function unblocks this thread, otherwise returns immediately without waiting and does nothing. So your for loop with 10 iterations is executed as soon as possible, without any waiting for pthread_cond_wait is called.
So can rewrite your for loop to infinite loop, calling pthread_cond_signal repeatedly.
if(pthread_create(&inc_x_thread, NULL, inc_x, E1_ptr)) {
printf("Error creating thread\n");
}
while(1) { // INFINITE LOOP
if(pthread_cond_signal(&count_threshold_cv)) {
printf("Error Signaling thread at sample = %d\n",i);
}
if (taskDone) // testing global flag, if 1 break
break; // it means inc_x thread has ended
}
if(pthread_join(inc_x_thread, NULL)) { // it was pointed out in comment
printf("Error joining thread\n"); // you need to join at the end of main function
}
taskDone is global int, with 0 as default value. It is set to 1 before pthread_exit is called in inc_x function. Setting/checking taskDone should be wrapped with some synchronization mechanism, for example by adding new mutex or use count_mutex.

How to make thread 2,3 and 4 wait for same signal from thread1?

I have a function to be executed by thread1,2,3,4.... Once thread1 gets access to the function, I use thread_cond for waiting for the other threads. Once thread1 does its work, I send thread_signal to the same cond. Thread2 is executing the function. But after it finishes execution, the other threads don't get access to the function.
Please help me
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
int limit = 0;
pthread_mutex_t mutex[100];
pthread_cond_t cond[100];
pthread_t tid[100];
void *enter()
{
if (limit == 1)
{
printf("waiting\n");
pthread_cond_wait(&cond[1],&mutex[1]);
}
gotofunction();
}
void gotofunction()
{
limit++;
/* Do work */
printf("Doing work\n");
sleep(1);
limit--;
printf("Going to give signal\n");
pthread_cond_signal(&cond[1]);
}
int main()
{
int n,i;
scanf("%d",&n);
for (i=0;i<100;i++)
{
pthread_mutex_init(&mutex[i], NULL);
pthread_cond_init(&cond[i], NULL);
}
for (i=0;i<n;i++)
{
pthread_create(&tid[i], NULL, enter, NULL);
sleep(0.5);
}
for (i=1;i<=n;i++)
{
pthread_join(tid[i], NULL);
}
}
Basically thread1 prints "doing work"
Thread2 prints "doing work"
Then nothing happens for the other threads
You must have the mutex that you passed to pthread_cond_wait() locked at the time you call it. That mutex must also be locked while you check and change the condition that the condition variable is paired with (in this case, limit == 1 is that condition).
You should also use the pattern while (condition) { pthread_cond_wait() } (rather than if (condition)), because the condition variable may wake up without the condition actually being true.
Changing your code to lock the mutex around the accesses to limit, and unlock it while simulating the work, looks like this:
void *enter()
{
pthread_mutex_lock(&mutex[1]);
while (limit == 1)
{
printf("waiting\n");
pthread_cond_wait(&cond[1],&mutex[1]);
}
gotofunction();
pthread_mutex_unlock(&mutex[1]);
return NULL;
}
void gotofunction()
{
limit++;
pthread_mutex_unlock(&mutex[1]);
/* Do work */
printf("Doing work\n");
sleep(1);
pthread_mutex_lock(&mutex[1]);
limit--;
printf("Going to give signal\n");
pthread_cond_signal(&cond[1]);
}
Of course when you check against a limit of 1, you could just use a plain mutex instead - but this scheme could be extended to allow N threads to execute work simultaneously, by changing the condition to while (limit >= N).

pthread_cond_wait and pthread_mutex_lock priority?

I have a multiple read threads and one write thread. If I lock mutex on one of the read threads and send broadcast from it, is it guaranteed that mutex will be locked by write thread waiting on pthread_cond_wait() or is there a possibility that another read thread that is wainting on pthread_mutex_lock() will lock mutex? Main question is does pthread_cond_wait() have priority over pthread_mutex_lock()?
If not, how can I achieve that the mutex will always be locked by write thread on pthread_cond_broadcast()?
Example
Read thread:
pthread_mutex_lock(mutex);
pthread_cond_broadcast(cond);
pthread_mutex_unlock(mutex);
Write thread:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
Let's assume both threads, read and write, reach the pthread_mutex_lock in the same moment. So, either write thread acquire the mutex on pthread_mutex_lock call, or read thread.
If it would be the write thread, the read one will wait on pthread_mutex_lock. The write, by calling pthread_cond_wait releases mutex and blocks on cond. It is done atomically. So, when read thread is grantex the mutex, we can be sure the the read one waits on cond. So, broadcast on cond reaches the write thread, it no more waits on cond but - still in scope of pthread_cond_wait - tries to get a lock on mutex (hold be read thread). After broadcasting cond the read thread releases the mutex and it goes to write thread. So write thread finally exits from pthread_cond_wait having the mutex locked. Remember to unlock it later.
If it would be the read thread, the write one will wait on pthread_mutex_lock, the read will broadcast a signal on cond then release the mutex. After then the write thread acquires the mutex on pthread_mutex_lock and immediately releases in it pthread_cond_wait waiting for cond (please note, that previous cond broadcast has no effect on current pthread_cond_wait). In the next iteration of read thread it acquires lock onmutex, send broadcast on cond and unlock mutex. It means the write thread moves forward on cond and acquires lock on mutex.
Does it answer your question about priority?
Update after comment.
Let's assume we have one thread (let's name it A for future reference) holding the lock on mutex and few other trying to acquire the same lock. As soon as the lock is released by first thread, there is no predictable which thread would acquire lock. Moreover, if the A thread has a loop and tries to reacquire lock on mutex, there is a chance it would be granted this lock and other threads would keep waiting. Adding pthread_cond_wait doesn't change anything in scope of granting a lock.
Let me quote fragments of POSIX specification (see https://stackoverflow.com/a/9625267/2989411 for reference):
These functions atomically release mutex and cause the calling thread to block on the condition variable cond; atomically here means "atomically with respect to access by another thread to the mutex and then the condition variable". That is, if another thread is able to acquire the mutex after the about-to-block thread has released it, then a subsequent call to pthread_cond_broadcast() or pthread_cond_signal() in that thread shall behave as if it were issued after the about-to-block thread has blocked.
And this is only guarantee given by standard regarding order of operations. Order of granting the lock to other threads is rather unpredictable and it changes depending on some very subtle fluctuation in timing.
For only mutex related code, please play a little with following code:
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *th(void *arg) {
int i;
char *s = arg;
for (i = 0; i < 10; ++i) {
pthread_mutex_lock(&mutex);
printf("%s %d\n", s, i);
//sleep(1);
pthread_mutex_unlock(&mutex);
#if 0
pthread_yield();
#endif
}
return NULL;
}
int main() {
int i;
for (i = 0; i < 10; ++i) {
pthread_t t1, t2, t3;
printf("================================\n");
pthread_create(&t1, NULL, th, "t1");
pthread_create(&t2, NULL, th, " t2");
pthread_create(&t3, NULL, th, " t3");
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
}
return 0;
}
On one machine (single CPU) it always shows whole loop from t3, then t2 and finally from t1. On another (2 cores) the order of threads is more random, but almost always it shows whole loop for each thread before granting the mutex to other thread. Rarely there is a situation like:
t1 8
t1 9
t3 0
t2 0
t2 1
[removed other t2 output]
t2 8
t2 9
t3 1
t3 2
Enable pthread_yield by replacing #if 0 with #if 1 and watch results and check output. For me it works in a way two threads display their output interlaced, then third thread finally has a chance to work. Add another or more thread. Play with sleep, etc. It confirms the random behaviour.
If you wish to experiment a little, compile and run following piece of code. It's an example of single producer - multiple consumers model. It can be run with two parameters: first is the number of consumer threads, second is the length of produced data series. If no parameters are given there is one consumer thread and 120 items to be processed. I also recommend with sleep/usleep in places marked /* play here */: change the value of arguments, remove the sleep at all, move it - when appropriate - to critical section or replace with pthread_yield and observe changes in behaviour.
#define _GNU_SOURCE
#include <assert.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
struct data_t {
int seq;
int payload;
struct data_t *next;
};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct data_t *first = NULL, *last = NULL;
int in_progress = 1;
int num_data = 120;
void push(int seq, int payload) {
struct data_t *e;
e = malloc(sizeof(struct data_t));
e->seq = seq;
e->payload = payload;
e->next = NULL;
if (last == NULL) {
assert(first == NULL);
first = last = e;
} else {
last->next = e;
last = e;
}
}
struct data_t pop() {
struct data_t res = {0};
if (first == NULL) {
res.seq = -1;
} else {
res.seq = first->seq;
res.payload = first->payload;
first = first->next;
if (first == NULL) {
last = NULL;
}
}
return res;
}
void *producer(void *arg __attribute__((unused))) {
int i;
printf("producer created\n");
for (i = 0; i < num_data; ++i) {
int val;
sleep(1); /* play here */
pthread_mutex_lock(&mutex);
val = rand() / (INT_MAX / 1000);
push(i, val);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
printf("prod %3d %3d signaled\n", i, val);
}
in_progress = 0;
printf("prod end\n");
pthread_cond_broadcast(&cond);
printf("prod end signaled\n");
return NULL;
}
void *consumer(void *arg) {
char c_id[1024];
int t_id = *(int *)arg;
sprintf(c_id, "%*s c %02d", t_id % 10, "", t_id);
printf("%s created\n", c_id);
while (1) {
struct data_t item;
pthread_mutex_lock(&mutex);
item = pop();
while (item.seq == -1 && in_progress) {
printf("%s waits for data\n", c_id);
pthread_cond_wait(&cond, &mutex);
printf("%s got signal\n", c_id);
item = pop();
}
if (!in_progress && item.seq == -1) {
printf("%s detected end of data.\n", c_id);
pthread_mutex_unlock(&mutex);
break;
}
pthread_mutex_unlock(&mutex);
printf("%s processing %3d %3d\n", c_id, item.seq, item.payload);
sleep(item.payload % 10); /* play here */
printf("%s processed %3d %3d\n", c_id, item.seq, item.payload);
}
printf("%s end\n", c_id);
return NULL;
}
int main(int argc, char *argv[]) {
int num_cons = 1;
pthread_t t_prod;
pthread_t *t_cons;
int i;
int *nums;
if (argc > 1) {
num_cons = atoi(argv[1]);
if (num_cons == 0) {
num_cons = 1;
}
if (num_cons > 99) {
num_cons = 99;
}
}
if (argc > 2) {
num_data = atoi(argv[2]);
if (num_data < 10) {
num_data = 10;
}
if (num_data > 600) {
num_data = 600;
}
}
printf("Spawning %d consumer%s for %d items.\n", num_cons, num_cons == 1 ? "" : "s", num_data);
t_cons = malloc(sizeof(pthread_t) * num_cons);
nums = malloc(sizeof(int) * num_cons);
if (!t_cons || !nums) {
printf("Out of memory!\n");
exit(1);
}
srand(time(NULL));
pthread_create(&t_prod, NULL, producer, NULL);
for (i = 0; i < num_cons; ++i) {
nums[i] = i + 1;
usleep(100000); /* play here */
pthread_create(t_cons + i, NULL, consumer, nums + i);
}
pthread_join(t_prod, NULL);
for (i = 0; i < num_cons; ++i) {
pthread_join(t_cons[i], NULL);
}
free(nums);
free(t_cons);
return 0;
}
I hope I have cleared your doubts and gave you some code to experiment and gain some confidence about pthread behaviour.

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);

Changing the function that a thread executes

I'm implementing the Dining Philosophers problem in c using pthreads.
Each philosopher is represented by a thread.
Each thread needs to be able to execute four different functions.
I'm aware that I can set a thread to execute a function with:
pthread_create(&tid, &atr, func1, NULL);
That's fine, but how do I make the thread execute a different function later on (i.e. func2).
Is there a way to change the function that a thread is executing or am I off the ball entirely?
Thanks
Here's a possibility, demonstrated with a single thread (aside from the main thread).
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int to_run = 0;
void func0() {
to_run = -1;
while (to_run == -1) putchar('-');
}
void func1() {
to_run = -1;
while (to_run == -1) putchar('*');
}
void *func(void *data) {
while (1) {
switch (to_run) {
case 0:
func0();
break;
case 1:
func1();
break;
case 2:
printf("\nDONE\n");
return NULL;
}
}
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
int i;
for (i=0; i<3; i++) {
sleep(1);
to_run = 1;
sleep(1);
to_run = 0;
}
to_run = 2;
pthread_join(tid, NULL);
return 0;
}
You shouldn't need to change the function the thread is running. You should represent each philosopher with a thread (as you said) and each fork with a mutex.
The philosopher threads will simply run a loop of 2 functions think then eat.
think is just a call to sleep.
eat will try to acquire the 2 mutexes that represent his adjacent forks. The philosopher thread will be blocked waiting for the mutexes to unlock. once they unlock then he can lock them himself (pickup_forks) and wait a short period of time (sleep) then unlock them (return_forks).
There is more to it than that, but it should get you past your current problem.
If your program freezes on a mutex lock. Its a deadlock and you may have to revise your algorithm to stop the deadlock.

Resources