Use semaphores in C to protect variable within for loop - c

I'm trying to use semaphores to avoid that a global variable is changed by threads and this variable is supposed to increment within the for loop. My main objective is to protect the variable cnt from the threads so it can increment within the for loop. However, I don't know how to do it because this is the first time I work with semaphores.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
sem_t semaphore;
int cnt = 0; //global shared variable
void *threadProd(void *param); //threads call this function.
int main(int argc, char *argv[])
{
int niters;
pthread_t tid1, tid2; //thread ids
sem_init(&semaphore,0,1);
if (argc != 2){
printf("Usage: %s <niters>\n", argv[0]);
exit(0);
}
niters = atoi(argv[1]);
pthread_create(&tid1, NULL, threadProd, &niters);
pthread_create(&tid2, NULL, threadProd, &niters);
pthread_join(tid1, NULL); //wait for thread to finish
pthread_join(tid2, NULL);
//check answer:
if(cnt != (2 * niters))
printf("Incorrect answer, cnt = %d\n", cnt);
else
printf("Correct answer, cnt = %d\n", cnt);
sem_destroy(&semaphore);
exit(0);
}
//Thread routine
void *threadProd(void *vargp)
{
sem_wait(&semaphore);
int upper = *((int *) vargp);
for (int i = 0; i < upper; i++)
cnt ++;
sem_post(&semaphore);
return NULL;
}

Related

Producer-Consumer solution runs but doesn't print

This is my current code for the Producer-Consumer problem. I compiled it and ran it but nothing is printed. The command line takes in 3 arguments: Sleep time, producer threads, consumer threads. I've tried setting the values as 5, 1, 1 respectively, the sleep timer works but I'm unsure about the rest.
Code for buffer.h:
typedef int buffer_item;
#define BUFFER_SIZE 5
Code for buffer.c:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "buffer.h"
buffer_item buffer[BUFFER_SIZE];
void *producer(void *param);
void *consumer(void *param);
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int insert_item(buffer_item item)
{
do
{
wait(empty);
wait(mutex);
signal(mutex);
signal(full);
}while(1);
return 0;
}
int remove_item(buffer_item *item)
{
do
{
wait(full);
wait(mutex);
signal(mutex);
signal(empty);
}while(1);
return 0;
}
int main(int argc, char *argv[])
{
int sleepTime;
int producerThreads;
int consumerThreads;
int counter_1;
int counter_2;
if(argc != 4)
{
return -1;
}
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
srand((unsigned)time(NULL));
for(counter_1 = 0; counter_1 < producerThreads; counter_1++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, producer, NULL);
}
for(counter_2 = 0; counter_2 < consumerThreads; counter_2++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, consumer, NULL);
}
sleep(sleepTime);
return 0;
}
void *producer(void *param)
{
buffer_item item;
int randomTime;
int counter_1 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
item = rand();
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Producer ID: %lu, Produced Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_1);
++counter_1;
}
}
}
void *consumer(void *param)
{
buffer_item item;
int randomTime;
int counter_2 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Consumer ID: %lu, Consumed Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_2);
++counter_2;
}
}
}
So far I've tried declaring the tid separately, skipping sleep and join the threads, but it still doesn't print.
Your code can't possibly run, indeed it doesn't even compile.
Here's a list of issues that need to be addressed:
wait should be sem_wait
signal should be sem_post for semaphores
int sem_wait(sem_t *sem); and int sem_post(sem_t *sem); take the pointer to a semaphore
sem_wait(mutex) and sem_post(mutex) give something like "incompatible type for argument 1 of sem_wait", I guess you want to acquire and release the lock on the mutex like pthread_mutex_lock(&mutex) and pthread_mutex_unlock(&mutex)
in the consumer if(insert_item(item)): item is used uninitialized
still in the consumer you use insert_item instead of remove_item
Coming to the main question "I compiled it and ran it but nothing is printed", it doesn't print anything because producer and consumer call, respectively, insert_item and remove_item and are trapped inside infinite loops (e.g. while(1))

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

Printing out even and odd numbers using thread in C

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_even(void* arg);
void* thread_odd(void* arg);
int main(int argc, char** argv) {
pthread_t tid[2];
pthread_create(&tid[0], 0, &thread_even, 0);
pthread_create(&tid[1], 0, &thread_odd, 0);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
void* thread_even(void* arg) {
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
{
if(i%2 != 0)
{
printf("Thread 1: %d", i);
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
void* thread_odd(void* arg) {
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
{
if(i%2 == 0)
{
printf("Thread 2: %d", i);
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
The above is the code I am working on but I get a segment fault error... What I want to achieve is, for example,
when I compile it and run with an argument 8 (./number 8)
it should print out
thread 1: 1
thread 2: 2
thread 1: 3
... etc till the number, 8.
in which thread 1s should represent the even numbers and the thread 2s stand for the odd numbers.
Please help... I want to develop my knowledge about C but have no one to ask..
Thanks.
Looks like you are passing 0 AKA NULL to the last parameter of pthread_create, and then doing the following:
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
So, thread_id will certainly be NULL, referencing it will be a SEGFAULT.
If you want to pass an upper bound for each thread to run to, do you can do something like this:
int main(int argc, char** argv) {
pthread_t tid[2];
int *ids = malloc(2 * sizeof(int));
ids[0] = 10; /* upper bound for thread 1 */
ids[1] = 10; /* upper bound for thread 2 */
pthread_create(&tid[0], 0, &thread_even, &ids[0]);
pthread_create(&tid[1], 0, &thread_odd, &ids[1]);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
free(ids);
return 0;
}
There are ways to do this without resorting to heap allocation, but this is the most straight forward.

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

Thread sync by using mutex and barrier in C

I am trying to use pthread mutex variables and barrier to synchronize the output of my program, but it is not working the way I want it to. Each thread is seeing its final value every 20 values (coming from the for loop) which is alright but I'm trying to make them all get to the same final value (if using 5 threads, all of them should see 100 as final value, with 4 threads, 80, etc)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int SharedVariable =0;
void *SimpleThread(void *args)
{
int num,val,rc;
int which =(int)args;
rc = pthread_mutex_lock(&mutex1);
for(num=0; num<20; num++){
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
//pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
//pthread_mutex_lock(&mutex1);
SharedVariable = val+1;
pthread_mutex_unlock(&mutex1);
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
//pthread_mutex_destroy(&mutex1);
//pthread_exit((void*) 0);
//pthread_mutex_unlock(&mutex1);
}
int main (int argc, char *argv[])
{
if(atoi(argv[1]) > 0){
int num_threads = atoi(argv[1]);
//pthread_mutex_init(&mutex1, NULL);
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_mutex_lock(&mutex1);
for(t=0; t< num_threads; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(thread1);
}
rc= pthread_mutex_unlock(&mutex1);
}
else{
printf("ERROR: The parameter should be a valid positive number.");
exit(-1);
}
pthread_mutex_destroy(&mutex1);
pthread_exit(NULL);
}
Any suggestions or help is greatly appreciated!
Thanks in advanced!
You need to use a barrier (pthread_barrier_wait()) before checking for the final value - this ensures that no thread will proceed until all threads have reached the barrier.
In addition, you should be calling pthread_join() to wait for the threads to finish, and you only need to hold the mutex around the increment:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
int SharedVariable = 0;
void *SimpleThread(void *args)
{
int num,val;
int which = (int)args;
for(num = 0; num < 20; num++) {
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val + 1;
pthread_mutex_unlock(&mutex1);
}
pthread_barrier_wait(&barrier1);
val = SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
return 0;
}
int main (int argc, char *argv[])
{
int num_threads = argc > 1 ? atoi(argv[1]) : 0;
if (num_threads > 0) {
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_barrier_init(&barrier1, NULL, num_threads);
if (rc) {
fprintf(stderr, "pthread_barrier_init: %s\n", strerror(rc));
exit(1);
}
for (t = 0; t < num_threads; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < num_threads; t++) {
pthread_join(threads[t], NULL);
}
}
else {
printf("ERROR: The parameter should be a valid positive number.\n");
exit(-1);
}
return 0;
}
Try to move the pthread_mutext_unlock(&mutext1) out of the for loop in your SimpleThread. You lock once and unlock mutiple(20) times in your original code.
Alternatively, you could move pthread_mutex_lock(&mutext1) into the for loop, just before you read and modify your SharedVariable. In this case, each thread's add-by-one operation may not consecutive but each thread will get the correct final value.
And before you read the final value of the SharedVariable, use a barrier to wait all the threads finish their job.

Resources