Synchronizing screen output with mutex and pthread - c

I'm playing with a fairly simple C example. The program creates two threads and starts them in parallel. Each thread is designed to modify a global variable using a Mutex, and print out the value.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int A=10;
pthread_mutex_t M;
void *codice_Th1(void *arg) {
int i;
for (i=0; i<10;i++){
pthread_mutex_lock(&M);
printf("Thread %s: ", (char *)arg);
A++;
printf("A = %d \n", A);
pthread_mutex_unlock(&M);
sleep(1);
}
pthread_exit(0);
}
void *codice_Th2(void *arg) {
int i;
for (i=0; i<10;i++){
pthread_mutex_lock(&M);
printf("Thread %s: ", (char *)arg);
A--;
printf("A = %d \n", A);
pthread_mutex_unlock(&M);
sleep(1);
}
pthread_exit(0);
}
The main() simply creates the thread, and join the main thread with thread 1 and 2.
int main(){
pthread_t th1, th2;
...
}
What bothers me, is that I get the following output
Thread th1: Thread th2: A = 11
A = 10
Thread th1: A = 11
Thread th2: A = 10
Thread th1: Thread th2: A = 11
A = 10
Thread th1: Thread th2: A = 11
A = 10
Thread th2: Thread th1: A = 9
A = 10
Thread th1: A = 11
Thread th2: A = 10
whereas I would expect every line to execute the printf statements in sequence, given they are inside a mutex.
In other words, I can't understand the ouput
Thread th2: Thread th1: A = 9
I would expect always something similar to
Thread NAME: A = VALUE
Am I missing something?

Never mind, I believe I found the issue. I did not initialize the Mutex with pthread_mutex_init(&M, NULL); before using it.
Setting
int main(){
pthread_t th1, th2;
int ret;
pthread_mutex_init(&M, NULL);
fixed the issue. I assume using pthread_mutex_init is a requirement. Unfortunately, skipping the mutex initialization din't produce any warning or error. The script silently compiled.

Related

I would like to get 4 separate prints: "This is a thread 1", "This is a thread 2" and so on

pthread_create in a for loop, this is my code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex;
void* helloWorld(void *i) {
pthread_mutex_lock(&mutex);
printf("This is a thread %d\n", *((int*) i));
pthread_mutex_unlock(&mutex);
return 0;
}
int main() {
pthread_mutex_init(&mutex, NULL);
pthread_t threads[4];
int i;
printf("Main Message\n");
for (i = 0; i < 4; i++) {
pthread_create(&threads[i], NULL, helloWorld, &i);
}
for (i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);\
}
pthread_mutex_destroy(&mutex);
return 0;
}
The order doesn't really matter as long as all 4 threads are working.
I've tried to use mutex but it didn't solve the issue.
My current output is pretty random, it can be 0000 or 0112 or anything else.
The problem is two-fold:
First of all you don't have control over when the threads run or in which order.
You pass the same pointer to all threads.
You can solve the second issue by passing the value if i to the threads. This is one of the few cases where it's considered okay to pass values instead of pointers:
pthread_create(&threads[i], NULL, helloWorld, (void*)(uintptr_t) i);
Then in the thread
printf("This is a thread %d\n", (int)(uintptr_t) i);
The first issue, about the order, you have to come up with some other way to synchronize the threads and how they notify each other. For example by using four condition signals, one for each thread, that you signal in the order you want the threads to execute.

C Pthread: Running only 10 threads simultaneously (what is the problem here)

So I'm very new to the whole concept of pthread in C but please hear me out. I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t endCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t startCond = PTHREAD_COND_INITIALIZER;
void * threadThingy(void * n){
pthread_cond_wait(&startCond, &mutex);
printf("%d: RAND: %d\n", *((int*)n), rand());
//Lock mutex before broadcasting to main thread
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&endCond);
pthread_mutex_unlock(&mutex);
free(n);
fflush(stdout);
return 0;
}
int main(void){
printf("Starting\n");
pthread_t threads[100];
int i = 0;
while(i < 10){
int *arg = malloc(sizeof(int));
*arg = i;
pthread_create(&threads[i], NULL, threadThingy, arg);
i++;
}
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&startCond);
int finished = 0;
while(finished <= 100){
pthread_cond_wait(&endCond, &mutex);
//Lock mutex so no other requests can come in
pthread_mutex_lock(&mutex);
finished++;
int *arg = malloc(sizeof(int));
*arg = 11;
pthread_create(threads[i], NULL, threadThingy, arg);
i++;
pthread_cond_broadcast(&startCond);
pthread_mutex_unlock(&mutex);
}
printf("Stopping\n");
sleep(1000);
}
The whole goal is to run (only) 10 threads simultaneously of the 100. My idea was to start 10 threads, than wait until one is finished and start another one. So I let the program wait until a thread returns, then I start a new one so the thread that just returned gets replaced. What have I missed? Because now I only get this as an output:
Starting
0: RAND: 1804289383
As mentioned by Lavigne958, in function threadThingy() there is deadlock caused by pthread_cond_wait() as it will acquire the lock. Again, you are trying to lock it in next line. This is causing deadlock.
There are a few things need to check:
You need to lock the mutex before calling pthread_cond_wait().
If you solve the above issue, using multiple condition variable with the same mutex may cause further deadlock.
If you are not joining the threads, it will be better to create detached threads using PTHREAD_CREATE_DETACHED attribute.
The problem of N number of threads running simultaneously can be solved with one semaphore OR one condition variable(and one mutex). Example with semaphore is given below.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mysem;
#define NUM_CONCURRENT_THREADS 4
#define MAX_THREADS 40
void *thread(void *arg)
{
printf("Thread id %ld: started\n", pthread_self());
sleep(5); // Do some work
printf("Thread id %ld: Exiting\n", pthread_self());
sem_post(&mysem);
return NULL;
}
int main()
{
pthread_t t[MAX_THREADS];
pthread_attr_t attr;
int rc, i = 0;
sem_init(&mysem, 0, NUM_CONCURRENT_THREADS);
rc = pthread_attr_init(&attr);
rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
printf("\nParent begin\n");
while(i < MAX_THREADS)
{
sem_wait(&mysem);
pthread_create(&t[i], &attr, thread, NULL);
i++;
}
printf("\nParent end.\n");
sem_destroy(&mysem);
return 0;
}
Please check blog Tech Easy for more information on threads.
in the function that your threads run, you start by waiting on a condition but you forgot to take the mutex before. So you first must take the mutex before waiting on the condition.
you have what we call a deadlock.
What happens is:
the first thread wakes up (the pthread_con_wait function acquires the lock for you already)
then you try to acquire the lock again => deadlock because you already own the lock so you kinda deadlock yourself.

C - synchronizing multiple threads w/ mutexs

I'm trying to synchronize multiple (7) threads. I thought I understood how they work until I was trying it on my code and my threads were still printing out of order. Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void *text(void *arg);
long code[] = {4,6,3,1,5,0,2}; //Order in which to start threads
int num = 0;
pthread_mutex_t lock; //Mutex variable
int main()
{
int i;
pthread_t tid[7];
//Check if mutex worked
if (pthread_mutex_init(&lock, NULL) != 0){
printf("Mutex init failed\n");
return 1;
}
//Initialize random number generator
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
//Create our threads
for (i=0; i<7; i++)
pthread_create(&tid[i], NULL, text, (void*)code[i]);
//Wait for threads to finish
for (i=0; i<7; i++){
if(pthread_join(tid[i], NULL)){
printf("A thread failed to join\n");
}
}
//Destroy mutex
pthread_mutex_destroy(&lock);
//Exit main
return 0;
}
void *text (void *arg)
{
//pthread_mutex_lock(&lock); //lock
long n = (long) arg;
int rand_sec = rand() % (3 - 1 + 1) + 1; //Random num seconds to sleep
while (num != n) {} //Busy wait used to wait for our turn
num++; //Let next thread go
sleep(rand_sec); //Sleep for random amount of time
pthread_mutex_lock(&lock); //lock
printf("This is thread %d.\n", n);
pthread_mutex_unlock(&lock); //unlock
//Exit thread
pthread_exit(0);
}
So here I am trying to make threads 0-6 print IN ORDER but right now they are still scrambled. The commented out mutex lock is where I originally had it, but then moved it down to the line above the print statement but I'm having similar results. I am not sure where the error in my mutex's are, could someone give a hint or point me in the right direction? I really appreciate it. Thanks in advance!
You cannot make threads to run in order with only a mutex because they go in execution in an unpredictable order.
In my approach I use a condition variable and a shared integer variable to create a queueing system. Each thread takes a number and when the current_n number is equal to the one of the actual thread, it enters the critical section and prints its number.
#include <pthread.h>
#include <stdio.h>
#define N_THREAD 7
int current_n = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t number = PTHREAD_COND_INITIALIZER;
void *text (void *arg) {
int i = (int)arg;
pthread_mutex_lock(&mutex);
while ( i > current_n ) {
pthread_cond_wait(&number, &mutex);
}
//i = current_n at this point
/*I use stderr because is not buffered and the output will be printed immediately.
Alternatively you can use printf and then fflush(stdout).
*/
fprintf(stderr, "I'm thread n=%d\n", i);
current_n ++;
pthread_cond_broadcast(&number);
pthread_mutex_unlock(&mutex);
return (void*)0;
}
int main() {
pthread_t tid[N_THREAD];
int i = 0;
for(i = 0; i < N_THREAD; i++) {
pthread_create(&tid[i], NULL, text, (void *)i);
}
for(i = 0; i < N_THREAD; i++) {
if(pthread_join(tid[i], NULL)) {
fprintf(stderr, "A thread failed to join\n");
}
}
return 0;
}
The output is:
I'm thread n=0
I'm thread n=1
I'm thread n=2
I'm thread n=3
I'm thread n=4
I'm thread n=5
I'm thread n=6
Compile with
gcc -Wall -Wextra -O2 test.c -o test -lpthread
Don't worry about the warnings.

pthreads program doesn't behave well

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

pthread creation not working properly

i have this piece of code:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
int number;
pthread_mutex_t *mutex;
pthread_t *threads;
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
time_t rawtime;
struct tm * time_start;
time ( &rawtime );
time_start = localtime ( &rawtime );
printf ( "The number %ld thread is created at time %s \n",tid, asctime (time_start));
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int i,rc;
printf("give threads");
scanf("%d",&number);
mutex = calloc( number, sizeof(*mutex));
threads = calloc(number, sizeof(*threads));
for (i = 0; i < number;i++) {
pthread_mutex_init( &mutex[i],NULL);
}
for(i=0; i<number; i++){
printf("In main: creating thread %d\n", i);
rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
return 0;
}
The purpose of this code is to ask the user to give the number of the threads that it is going to create and after the creation of the threads,the thread itself will print 2 messages saying the number of the thread and the time that it was created.
The problem is that inside the main the message "In main: creating thread" is showing up but the message inside the threads sometimes does not.
For example, it would create 3 threads and only 1 thread will show up its message and that thread also will not show up the time that was created. I dont know if there is something wrong with the code.
Root Cause:
Your main() exits before the child threads get an opportunity to complete their task.
Solution:
You need to make sure that the main() waits until all the threads have completed their work.
You need to use:
pthread_join()
to achieve this functionality. Add the following before returning from main():
for(i=0; i<number; i++)
{
pthread_join(threads[i], NULL);
}
Other problems:
You allocate memory dynamically but never deallocate it. Eventhough, the OS reclaims the memory once your program returns. It is a good practice to do so explicitly.
You created a mutex but you neither use it, nor deallocate it. But that seems to be code in progress.
Return from main() is equivalent to calling exit(...), which terminates the whole process. You may use pthread_join() to wait for each non-main thread, like another answer advises, or you may call pthread_exit(NULL) in the end of your main(): it would exit the initial thread, but other threads will continue to run.

Resources