C thread parallel programming - c

I tried to make a parallel program that generates a random number with one thread and the other thread writes it.
Am I doing something wrong that messes with the performance/optimization? I ask it because it was very easy to write this program so I'm a little concerned that I am doing something wrong.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include "produceConsume.h"
#define NUM_THREAD 1
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int queue[1];
int queueCounter = 0;
void *producer(void *args)
{
while (1)
{
pthread_mutex_lock(&lock);
int n = rand() % 100;
queue[queueCounter] = n;
queueCounter++;
pthread_cond_wait(&cond, &lock);
pthread_mutex_unlock(&lock);
}
}
void *consumer(void *args)
{
while (1)
{
pthread_mutex_lock(&lock);
printf("%d\n", queue[queueCounter - 1]);
queueCounter--;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
sleep(1);
}
}
int main()
{
system("clear");
srand(time(NULL));
pthread_t th[NUM_THREAD], th2[NUM_THREAD];
for (int i = 0; i < NUM_THREAD; i++)
{
pthread_create(&th[i], NULL, &producer, NULL);
pthread_create(&th2[i], NULL, &consumer, NULL);
}
for (int i = 0; i < NUM_THREAD; i++)
{
pthread_join(th[i], NULL);
pthread_join(th2[i], NULL);
}
}

You don't need an array if you are going to use only one thread, in any case, you create two threads but only one is joined (leaking memory), instead:
pthread_t th1[NUM_THREAD]; // or simply pthread_t th1;
pthread_t th2[NUM_THREAD]; // or simply pthread_t th2;
for (int i = 0; i < NUM_THREAD; i++)
{
pthread_create(&th1[i], NULL, &producer, NULL);
pthread_create(&th2[i], NULL, &consumer, NULL);
}
for (int i = 0; i < NUM_THREAD; i++)
{
pthread_join(th1[i], NULL);
pthread_join(th2[i], NULL);
}

Related

How to take input whenever I want during endless loop?

My task is to make a game simulation that uses threads to simulate work. If the thread's been given command to do another work it should pause it's first work and start the new work. How to implement it in C? I've tried with separate function for the input and signaling a condition variable but when it enters the giveCommand() function it just waits for input.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
char command;
pthread_mutex_t mutex;
pthread_cond_t condVar;
void giveCommand()
{
scanf("%c", command);
pthread_cond_signal (&condVar);
return;
}
void *thread(void *N)
{
char c;
do
{
pthread_mutex_lock(&mutex);
//do its work
pthread_cond_timedwait(&condVar, &mutex, 500000);// if command hasn't been given, continue work
pthread_mutex_unlock(&mutex);
pthread_cond_init(&condVar, NULL);
while(giveCommand());
}
}
int main()
{
int i;
int error;
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condVar, NULL);
while(1)
{
for (i = 0; i < NUM_THREADS; i++)
{
error = pthread_create(&threads[i], NULL, simulateWorker, NULL);
if (error != 0) printf("Error creating thread!");
}
for (i = 0; i < NUM_THREADS; i++)
{
error = pthread_join(threads[i], NULL);
if (error != 0) printf("Error joining thread!");
}
pthread_mutexattr_destroy(&mutex);
}
return 0;
}

My code spent long time when I use mutex_lock inside loop

When I use mutex_lock inside loop, my code spends huge time in execution, and I can't get the output.
I know lock () take time, but not as this!
I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int x = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *fnC()
{
int i;
for (i = 0; i < 2; i++)
{
pthread_mutex_lock(&mutex);
x++;
}
printf(" %d", x);
pthread_mutex_unlock(&mutex);
}
int main()
{
int rt1, rt2;
pthread_t t1, t2;
/* Create two threads */
if ((rt1 = pthread_create(&t1, NULL, &fnC, NULL)))
printf("Thread creation failed: %d\n", rt1);
if ((rt2 = pthread_create(&t2, NULL, &fnC, NULL)))
printf("Thread creation failed: %d\n", rt2);
/* Wait for both threads to finish */
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("\n");
return 0;
}
Anyone can explain this?

(C, pthreads) Let multiple threads synchronize and continue together

I have a program which consists of multiple threads.
These threads have to synchronize at some point, continue together, do their work of different lengths and then synchronize again.
Here's the example of what I mean:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 10
void* thread(void* idp);
int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int main(int args, char **argv)
{
pthread_mutex_t mutex_var;
pthread_cond_t cond_var;
mutex = &mutex_var;
cond = &cond_var;
pthread_mutex_init(mutex, NULL);
pthread_cond_init(cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating Thread %d....\n", i);
int* id = malloc(sizeof(int));
*id = i;
if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
{
perror("Error while creating the threads");
exit(1);
}
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
void* thread(void* idp)
{
int* id = (int*) idp;
while (1)
{
sleep(*id+2); // Thread work
pthread_mutex_lock(mutex);
threads_running++;
pthread_mutex_unlock(mutex);
pthread_cond_broadcast(cond);
printf("Thread %d WAIT\n", *id);
fflush(stdout);
// Let threads synchronize
pthread_mutex_lock(mutex);
while(threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_mutex_unlock(mutex);
printf("Thread %d WAKEUP\n", *id);
fflush(stdout);
// and continue
pthread_mutex_lock(mutex);
threads_running--;
pthread_mutex_unlock(mutex);
}
}
The thing that happens, is that some (usually #9 and one or two others) reach Thread %d WAKEUP but before the others can wake-up threads_running is already smaller than NUM_THREADS.
How can I synchronize multiple threads, so they continue together?
I am having some trouble wrapping my head around the parallel accesses to variables.
I found the answer seconds later:
Change while(threads_running != NUM_THREADS) to while(threads_running != 0 && threads_running != NUM_THREADS)
Change threads_running--; to threads_running = 0;
Now it works perfectly.
I recommend using pthread_cond_signal() than pthread_cond_broadcast(cond);
So the code flow where while loop is exiting looks like below.
pthread_mutex_lock(mutex);
while(threads_running != 0 && threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_cond_signal(cond);
So the final code looks like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 10
void* thread(void* idp);
int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int main(int args, char **argv)
{
pthread_mutex_t mutex_var;
pthread_cond_t cond_var;
mutex = &mutex_var;
cond = &cond_var;
pthread_mutex_init(mutex, NULL);
pthread_cond_init(cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating Thread %d....\n", i);
int* id = malloc(sizeof(int));
*id = i;
if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
{
perror("Error while creating the threads");
exit(1);
}
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
void* thread(void* idp)
{
int* id = (int*) idp;
while (1)
{
sleep(*id+2); // Thread work
pthread_mutex_lock(mutex);
threads_running++;
pthread_mutex_unlock(mutex);
printf("Thread %d WAIT\n", *id);
fflush(stdout);
// Let threads synchronize
pthread_mutex_lock(mutex);
while(threads_running != 0 && threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_cond_signal(cond);
pthread_mutex_unlock(mutex);
printf("Thread %d WAKEUP\n", *id);
fflush(stdout);
// and continue
pthread_mutex_lock(mutex);
threads_running = 0;
pthread_mutex_unlock(mutex);
}
}

UNIX Pthreads & mutex; program locks up

Following scenario:
We are supposed to make x Threads maximum. Our main-function is supposed to make a single new thread with a pointer to the function 'makeThreads'. This function is supposed to make up to 2 threads, depending on how many threads are already there. Race conditions are to avoid.
I'm stuck. I'm not exactly sure how to solve the problem I'm running into, partly because I don't can't identify the problem itself.
Suggestions are greatly appreciated!
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#define MAX_THR 20
pthread_mutex_t mutex;
int threadCount = 0;
int randomNbr(){
int number = (rand() % 10) + 1;
return number;
}
void *makeThreads(void* number){
int rndnmb = *((int *) number);
pthread_mutex_lock(&mutex);
sleep(rndnmb);
pthread_t threadDummy;
int thread1, i, threadID, rndnbr;
threadID = threadCount;
printf("Hello from Thread %d!\n", threadID);
for(i = 0; i < 2; i++){
if(threadCount < MAX_THR){
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
thread1 = pthread_create(&threadDummy, NULL, *makeThreads, (void *) rnd);
pthread_join(threadDummy, NULL);
}
}
pthread_mutex_unlock(&mutex);
printf("Goodbye from Thread %d!\n", threadID);
}
int main(){
int t1, rndnbr;
pthread_t threadOne;
pthread_mutex_init(&mutex, NULL);
srand(time(NULL));
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
t1 = pthread_create(&threadOne, NULL, *makeThreads, (void *) rnd);
pthread_join(threadOne, NULL);
}

Is one Boolean variable per thread redundant?

I wrote this code in order to better understand producer consumer in a program where I require threads to wait for a task and then work in parallel to complete it.
I am wondering if I really needed an array for the conditionMet integer variables?
Could I not do the same with one integer?
Was there anything I could do to simplify the code?
My goal is to allow the main thread to hand tasks to the other threads.
Since this is just the skeleton, I am wondering if there is a way to simplify it?
#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define NTHREADS 7
#define RUN_N_TIMES 3
pthread_cond_t new_task_available = PTHREAD_COND_INITIALIZER;
pthread_cond_t task_complete = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
volatile int producerCond = 0;
volatile int conditionMet[NTHREADS] = {};
volatile int no_more_tasks = 0;
volatile int mini_tasks_complete = - NTHREADS;
void do_work(unsigned int* current_level){
++*current_level;
printf("Thread %u has completed %u units of work.\nIt was #%d to complete it's task this round..\n", (unsigned int)pthread_self(), *current_level, mini_tasks_complete);
}
void *threadfunc(void *parm)
{
int* thread_cond;
unsigned int level = 0;
thread_cond = (int*)parm;
while(!no_more_tasks){
pthread_mutex_lock(&mutex);
++mini_tasks_complete;
if(mini_tasks_complete == NTHREADS){
producerCond = 1;
pthread_cond_signal(&task_complete);
}
threads_waiting++;
*thread_cond = 0;
while (!*thread_cond) {
pthread_cond_wait(&new_task_available, &mutex);
if(no_more_tasks)
{
pthread_mutex_unlock(&mutex);
return NULL;
}
}
pthread_mutex_unlock(&mutex);
do_work(&level);
}
return NULL;
}
void reset_cond(int val){
int i;
for (i=0; i<NTHREADS; ++i)
conditionMet[i] = val;
}
int main(int argc, char **argv)
{
int i;
pthread_t threadid[NTHREADS];
for(i=0; i < NTHREADS; ++i) {
pthread_create(&threadid[i], NULL, threadfunc, &(conditionMet[i]));
}
while(threads_waiting < NTHREADS)
sleep(1); /* Sleep is not a very robust way to serialize threads */
/* The condition has occured. Set the flag and wake up any waiting threads */
printf("Waking up all waiting threads " "#RUN_N_TIMES" " times...\n");
for(i = 0; i < RUN_N_TIMES; i++){
pthread_mutex_lock(&mutex);
mini_tasks_complete = 0;
printf("New tasks available.\n");
sleep(1);
reset_cond(1);
pthread_cond_broadcast(&new_task_available);
producerCond = 0;
while (!producerCond) {
printf("Main waiting\n");
pthread_cond_wait(&task_complete, &mutex);
}
pthread_mutex_unlock(&mutex);
}
no_more_tasks = 1;
pthread_mutex_lock(&mutex);
mini_tasks_complete = 0;
printf("Go home everybody!\n");
pthread_cond_broadcast(&new_task_available);
pthread_mutex_unlock(&mutex);
printf("Wait for threads and cleanup\n");
for (i=0; i<NTHREADS; ++i) {
pthread_join(threadid[i], NULL);
}
pthread_cond_destroy(&new_task_available);
pthread_cond_destroy(&task_complete);
pthread_mutex_destroy(&mutex);
printf("Main done\n");
return 0;
}

Resources