how to synchronize process using mutex with multithreading in c - c

HI I am writing a program which write the string in file, process 1 will write a small letters in file and process 2 write a capital letters in same file. i implemented a program using threading, process 1 must run first, after that run the process 2 . program as follows.
/******************
* Header Files
******************/
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
pthread_mutex_t lock;
void* write_p1()
{
if((pthread_mutex_lock(&lock)) != 0)
{
printf("pthread_mutex_lock() failed\n");
exit(1);
}
int index=0; /*used in for loop*/
int flag=0; /*flag used in capital letter and space detecion*/
FILE *fp=NULL; /*file pointer used to store open file*/
char str[100]; /*to store user string*/
printf("*****Hi, I am Process 1*****\n");
/*open the sample.txt file for write*/
fp=fopen("sample.txt","w");
if(fp==NULL)
{
printf("Not able to open file\n");
exit(1);
}
printf("Enter small letters\n");
fgets(str,100,stdin);
/*capital letter and space detection*/
if((strlen(str)>0)&&(str[strlen(str)-1]=='\n'))
{
str[strlen(str)-1]='\0';
}
for(index=0;str[index]!='\0';index++)
{
if(islower(str[index]) || str[index] == ' ')
{
flag=0;
}
else
{
printf("Enter Small Letters\n");
exit(1);
}
}
if(flag==0)
{
fprintf(fp,"%s",str);
}
/*close the file*/
fclose(fp);
printf("Entered string: %s\n",str);
if((pthread_mutex_unlock(&lock)) != 0)
{
printf("pthread_mutex_unlock() failed\n");
exit(1);
}
printf("\n\n");
}
void* write_p2()
{
if((pthread_mutex_lock(&lock)) != 0)
{
printf("pthread_mutex_lock() failed\n");
exit(1);
}
int index=0; /*used in for loop*/
int flag=0; /*flag used in small letter and space detecion*/
FILE *fp=NULL; /*file pointer used to store open file*/
char str[100]; /*to store user string*/
printf("*****Hi, I am Process 2*****\n");
/*open the sample.txt file for write*/
fp=fopen("sample.txt","a");
if(fp==NULL)
{
printf("Not able to open file\n");
exit(1);
}
printf("Enter Capital letters\n");
fgets(str,100,stdin);
/*capital letter and space detection*/
if((strlen(str)>0)&&(str[strlen(str)-1]=='\n'))
{
str[strlen(str)-1]='\0';
}
for(index=0;str[index]!='\0';index++)
{
if(isupper(str[index]) || str[index] == ' ')
{
flag=0;
}
else
{
printf("Enter capital Letters\n");
exit(1);
}
}
if(flag==0)
{
fprintf(fp,"%s",str);
}
/*close the file*/
fclose(fp);
printf("Entered string: %s\n",str);
if((pthread_mutex_unlock(&lock)) != 0)
{
printf("pthread_mutex_unlock() failed\n");
exit(1);
}
printf("\n\n");
}
int main(void)
{
/*initialized semaphore*/
if((pthread_mutex_init(&lock,NULL)) != 0)
{
printf("pthread_mutex_init() failed\n");
exit(1);
}
/*create a two thread*/
pthread_t t1=0,t2=0;
pthread_create(&t1,NULL,write_p1,NULL);
pthread_create(&t2,NULL,write_p2,NULL);
/*this function wait for thread to terminate*/
pthread_join(t1,NULL);
pthread_join(t2,NULL);
/*destroy the semaphore*/
if((pthread_mutex_destroy(&lock)) != 0)
{
printf("pthread_mutex_destroy() failed\n");
exit(1);
}
return 0;
}
Now This program is working but sometime it will run first thread 2(process 2) or some time thread 1(process 1) , i need a solution for that, it must run thread 1(process 1) first after that thread 2(process 2), so what changes should i do?

I am wring below program for you. You can do it by using conditional variable. Implement same procedure in your code. How will it work? To start the controlling process, we allowing thread1 first. In the main thread (i.e. main function; every program has one main thread, in C/C++ this main thread is created automatically by the operating system once the control passes to the main method/function via the kernel) we are calling pthread_cond_signal(&cond1);. Once this function is called from the main thread, thread1, which was waiting on cond1, will be released and it will start executing further. Once it finishes its final task, it will call pthread_cond_signal(&cond2);. Now, the thread which was waiting on condition cond2, i.e. thread2, will be released and it will start to execute its final stage
#include<pthread.h>
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
int TRUE = 1;
void * threadMethod1(void *arg)
{
printf("In thread1\n");
do{
pthread_mutex_lock(&lock1);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond1, &lock1);
printf("I am thread1 generating the final report and inserting into file \n");
pthread_cond_signal(&cond2);/* Now allow 2nd thread to process */
pthread_mutex_unlock(&lock1);
}while(TRUE);
pthread_exit(NULL);
}
void * threadMethod2(void *arg)
{
printf("In thread2\n");
do
{
pthread_mutex_lock(&lock2);
//Add your business logic(parallel execution codes) here
pthread_cond_wait(&cond2, &lock2);
printf("I am thread2 generating the final report and inserting into a file \n");
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&lock2);
}while(TRUE);
pthread_exit(NULL);
}
int main(void)
{
pthread_t tid1, tid2;
int i = 0;
printf("Before creating the threads\n");
if( pthread_create(&tid1, NULL, threadMethod1, NULL) != 0 )
printf("Failed to create thread1\n");
if( pthread_create(&tid2, NULL, threadMethod2, NULL) != 0 )
printf("Failed to create thread2\n");
pthread_cond_signal(&cond1);/* Now allow first thread to process first */
sleep(1);
TRUE = 0;/* Stop all the thread */
//sleep(3);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
exit(0);
}

Related

How do I block the child threads while the parent thread waits for a user input?

I have a parent thread which creates child threads A,B,C,D,E,F. Each of these child threads runs a different disk scheduling algorithm and prints the result simultaneously. The task is to block these child threads while the parent thread waits for the user to input a file name, from which the disk scheduling data is parsed and read in order to be used in the disk scheduling algorithms for the child threads.
Currently my program first takes the user input before the creation of the child threads and therefor there is no need to block however my task is to block them.
#define N 71
typedef struct
{
int totalCylinders;
int cylindersInReqQueue;
int currentPos;
int prevDiskRequest;
int *requestQueueArr;
char id;
char *filename;
} disk_data;
sem_t semaphore;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;
void *runner(void *args);
void runscheduler(char name, disk_data data);
void *runner(void *args)
{
disk_data data = *(disk_data*)args;
char threadName = data.id;
pthread_mutex_lock(&mutex);
while(strlen(data.filename) == 0)
{
printf("IT REACHED THIS> GOING OUT");
pthread_cond_wait(&cond1, &mutex);
}
printf("Hello from thread %u I am %c\n", (int)pthread_self(),threadName);
runscheduler(threadName,data);
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void runscheduler(char name, disk_data data)
{
switch(name)
{
case 'A' :
firstComeFirstServe(data.cylindersInReqQueue, data.currentPos, data.requestQueueArr);
break;
case 'B' :
shortestSeekTimeFirst(data.totalCylinders, data.cylindersInReqQueue, data.currentPos, data.requestQueueArr);
break;
case 'C' :
scan(data.totalCylinders, data.currentPos, data.prevDiskRequest, data.cylindersInReqQueue, data.requestQueueArr);
break;
case 'D' :
cScan(data.totalCylinders, data.currentPos, data.prevDiskRequest, data.cylindersInReqQueue, data.requestQueueArr);
break;
case 'E' :
look(data.totalCylinders,data.currentPos,data.prevDiskRequest,data.cylindersInReqQueue,data.requestQueueArr);
break;
case 'F' :
cLook(data.totalCylinders,data.currentPos,data.prevDiskRequest,data.cylindersInReqQueue,data.requestQueueArr);
break;
default :
printf("Invalid grade\n" );
}
}
int main(int argc, char*argv[])
{
disk_data dd;
pthread_t tid[N];
int* res;
char *input;
int i,ret;
dd.cylindersInReqQueue =0;
dd.requestQueueArr = (int *) malloc(dd.cylindersInReqQueue * sizeof(int));
pthread_mutex_init(&mutex, NULL);
printf("***Disk Scheduler Simulation***");
input = readAndParse(&dd.totalCylinders, &dd.cylindersInReqQueue, &dd.currentPos, &dd.prevDiskRequest, &dd.requestQueueArr);
dd.filename = input;
for(i = 65; i < N; i++)
{
dd.id = (char)i;
ret = pthread_create(&tid[i], NULL, &runner, &dd);
if(ret != 0)
{
perror("Error: pthread_create() failed\n");
}
sleep(1);
printf ("Thread %c is created\n", i);
}
for(i = 65; i < N; i++)
{
if (pthread_join(tid[i], (void **) &res) != 0)
{
perror("Failed to join thread");
}
printf ("Thread %c has terminated\n", i);
}
pthread_mutex_destroy(&mutex);
printf ("All threads are now finished\n");
pthread_exit(NULL);
return 0;
}

Program with multiple threads always giving same output

I'm learning multi-threading and trying to create a program that can print two strings alternately.
I have written the following code :
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_mutex_t lock;
void print(char a[50]){
pthread_mutex_lock(&lock);
printf("%s", a); //output console is the shared resource
sleep(2);
pthread_mutex_unlock(&lock);
}
void* hello(void* status){
while(*((char*)status) != '\n'){
print("Hello World\n");
}
}
void* bye(void* status){
while(*((char*)status) != '\n'){
print("Goodbye World\n");
}
}
int main(){
pthread_t id1, id2;
char status = '\0';
int state;
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("\n mutex init has failed\n");
exit(1);
}
printf("Starting Threads (Press Enter to terminate)\n");
state = pthread_create(&id1, NULL, hello, &status);
if(state != 0){
printf("Could not create thread, exiting.\n");
exit(1);
}
state = pthread_create(&id2, NULL, bye, &status);
if(state != 0){
printf("Could not create thread, exiting.\n");
exit(1);
}
scanf("%c", &status);
printf("Out of The Threads\n");
pthread_mutex_destroy(&lock);
return 0;
}
According to what I understand, the mutex should lock the print function once for the hello function and then for the bye function. But I only get this output:
Starting Threads (Press Enter to terminate)
Hello World
Hello World
Hello World
Hello World
Hello World
Why does only the hello function get allocated the print function? How do I get it do print both?
Because, you use infinitive while in each function hello and bye. When the first thread starts, it never exits the while loop unless you press enter.
But when you type enter, the loop conditions in all functions will be false, so two threads will never touch print function again.
OT, you forget to join the threads.
Try to delete the while loop in each function and use it in main function, and see what happen. For example the program below (it may be not optimized, but i just want to show why your program always print Hello World:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_mutex_t lock;
void print(char a[50]){
pthread_mutex_lock(&lock);
printf("%s", a); //output console is the shared resource
sleep(2);
pthread_mutex_unlock(&lock);
}
void* hello(void* status){
// while(*((char*)status) != '\n'){
print("Hello World\n");
//}
}
void* bye(void* status){
//while(*((char*)status) != '\n'){
print("Goodbye World\n");
// }
}
int main(){
pthread_t id1, id2;
char status = '\0';
int state;
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("\n mutex init has failed\n");
exit(1);
}
printf("Starting Threads (Press Enter to terminate)\n");
while(status != '\n') {
state = pthread_create(&id1, NULL, hello, &status);
if(state != 0){
printf("Could not create thread, exiting.\n");
exit(1);
}
state = pthread_create(&id2, NULL, bye, &status);
if(state != 0){
printf("Could not create thread, exiting.\n");
exit(1);
}
pthread_join(id1, NULL);
pthread_join(id1, NULL);
scanf("%c", &status);
}
printf("Out of The Threads\n");
pthread_mutex_destroy(&lock);
return 0;
}

Problems with shared buffer and synchronized programming

I just started learning how to mess with threads and synchronized programming in C. I'm trying to code a reader which uses threads (POSIX interface) to read selected files from a shared buffer. The children threads will retrieve the file names from the buffer, while the father thread will be infinitly reading filenames from stdin and placing them in the buffer. What am I doing wrong?
pthread_mutex_t lock;
static char* files[NFILES];
int top = NFILES-1;
void putInBuffer(char* file){
pthread_mutex_lock(&lock);
if(top < NFILES-1){
files[top] = file;
top++;
}
pthread_mutex_unlock(&lock);
}
char* removeFromBuffer(){
char* file;
pthread_mutex_lock(&lock);
file = files[top];
top--;
pthread_mutex_unlock(&lock);
return file;
}
void* leitor(){
int op,i,r,cl;
char* file;
char buff[NCHARS];
char teste[NCHARS];
while(1){
pthread_mutex_lock(&lock);
file = removeFromBuffer();
printf("%s\n", file);
op = open(file, O_RDONLY);
if(op == -1) {
perror("Open unsuccessful");
pthread_exit((void*)-1);
}
r = read(op, teste, NBYTES);
if(r == -1){
perror("Read unsuccessful");
pthread_exit((void*)-1);
}
for(i=0; i<NLINES-1; i++){
r = read(op, buff, NBYTES);
if(r == -1){
perror("Read unsuccessful");
pthread_exit((void*)-1);
}
if(strcmp(buff,teste) != 0){
perror("Incorrect file");
pthread_exit((void*)-1);
}
}
cl = close (op);
if(cl == -1){
perror("Close unsuccessful");
pthread_exit((void*)-1);
}
printf("Correct file: %s\n", file);
pthread_mutex_unlock(&lock);
}
pthread_exit((void*)0);
return NULL;
}
int main(){
pthread_t threads[NTHREADS];
int i,*status;
char file[LENFILENAME];
if (pthread_mutex_init(&lock, NULL))
{
perror("\n mutex init failed\n");
exit(-1);
}
for(i=0;i<NTHREADS;i++){
if(pthread_create(&(threads[i]),NULL, leitor,NULL)){
perror("Failed to create thread");
exit(-1);
}
}
while(1){
read(STDIN_FILENO, file, LENFILENAME);
printf("%s\n", file);
putInBuffer(file);
printf("%s\n", removeFromBuffer());
}
for (i=0;i<NTHREADS;i++){
if(pthread_join(threads[i],(void**)&status)){
perror("Failed to join thread");
exit(-1);
}
printf("Thread returned %d\n", status);
}
pthread_mutex_destroy(&lock);
return 0;
}
Given what your program is doing, it seems that you should use a separate semaphore for notifying the child threads of new input instead of using the mutex that you have created.
Each child thread should wait on the semaphore at the top of the while loop, where you currently have pthread_mutex_lock(). After the parent has finished putInBuffer, it should release the semaphore once. When a child thread grabs the semaphore, it can call removeFromBuffer to get the next file, and read it (i.e. what you have already written). After the child finishes with the file, it should not release the semaphore, just go back to the top of the loop and wait on it again.
You have correctly used the mutex in putInBuffer and removeFromBuffer to protect accesses to the shared variables files and top.

Cat unix command multithread implementation

Hi im trying to implement faster cat than the one provided.
My current implementation looks like this:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define BUF_SIZE 1024*1024*1024
char buffer[BUF_SIZE];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_var2 = PTHREAD_COND_INITIALIZER;
int readed = 0;
/*
Read characters from standard input and saves them to buffer
*/
void *consumer(void *data) {
int r;
while(1) {
//---------CRITICAL CODE--------------
//------------REGION------------------
pthread_mutex_lock(&mutex);
if (readed > 0)
{
pthread_cond_wait(&cond_var2, &mutex);
}
r = read(0, buffer, BUF_SIZE);
readed = r;
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&mutex);
//------------------------------------
if (r == -1){
printf("Error reading\n");
}
else if (r == 0) {
pthread_exit(NULL);
}
}
}
/*
Print chars readed by consumer from standard input to standard output
*/
void *out_producer(void *data) {
int w;
while(1){
//---------CRITICAL CODE--------------
//-------------REGION-----------------
pthread_mutex_lock(&mutex);
if (readed == 0)
{
pthread_cond_wait(&cond_var, &mutex);
}
w = write(1, buffer, readed);
readed = 0;
pthread_cond_signal(&cond_var2);
pthread_mutex_unlock(&mutex);
//------------------------------------
if (w == -1){
printf("Error writing\n");
}
else if (w == 0) {
pthread_exit(NULL);
}
}
}
What would you suggest to make it faster?
Any ideas?
I was thinking about the BUF_SIZE, what would you think would be optimal size of buffer?
Main just makes the threads:
int main() {
// Program RETURN value
int return_value = 0;
// in - INPUT thread
// out - OUTPUT thread
pthread_t in, out;
// Creating in thread - should read from standard input (0)
return_value = pthread_create(&in , NULL, consumer, NULL);
if (return_value != 0) {
printf("Error creating input thread exiting with code error: %d\n", return_value);
return return_value;
}
// Creating out thread - should write to standard output (1)
return_value = pthread_create(&out, NULL, out_producer, NULL);
if (return_value != 0) {
printf("Error creating output thread exiting with code error: %d\n", return_value);
return return_value;
}
return_value = pthread_join(in, NULL);
return_value = pthread_join(out, NULL);
return return_value;
}
How exactly is adding threads to cat going to make it faster? You can't just throw parallelism at any program and expect it to run faster.
Cat basically just transports every line of input (usually from a file) to output. Since it's important that the lines are in order, you have to use mutual exclusion to avoid racing.
The upper bound of the speed (the fastest that cat can run) in parallel cannot be higher than cat in serial, since every thread must perform the serial actions, along with the cost of synchronization.

Check thread ending condition

I have a process with 2 threads. if one of the 2 threads is done executing his instructions, then the other should stop too. And the process should end. How to check if one of the threads has done executing the instructions? This is the code that i have written so far.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int read = 0;
int timeLeft = 0;
void *readFromFile(void *myFile){
char *theFile;
theFile = (char*) myFile;
char question[100];
char answer[100];
FILE *file = fopen(theFile, "r");
if(file != NULL){
while(fgets(question,sizeof question,file) != NULL){
fputs(question, stdout);
scanf("%s", &answer);
}
read = 1;
fclose(file);
printf("Done with questions!\n");
pthread_exit(
}
else{
perror(theFile);
}
}
void displayTimeLeft(void *arg){
int *time;
time = (int*) arg;
int i;
for(i = time; i >= 0; i -= 60){
if( i / 60 != 0){
printf("You have %d %s left.\n", i/60,(i/60>1)?"minutes":"minute");
sleep(60);
}
else{
timeLeft = 1;
printf("The time is over \n");
break;
}
}
}
int main(){
pthread_t thread1;
pthread_t thread2;
char *file = "/home/osystems01/laura/test";
int *time = 180;
int ret1;
int ret2;
ret1 = pthread_create(&thread1, NULL, readFromFile,&file);
ret2 = pthread_create(&thread2, NULL, displayTimeLeft,&time);
printf("Main function after pthread_create");
while(1){
//pthread_join(thread1,NULL);
//pthread_join(thread2,NULL);
if(read == 1){
pthread_cancel(thread2);
pthread_cancel(thread1);
break;
}
else if(timeLeft == 0){
pthread_cancel(thread1);
pthread_cancel(thread2);
break;
}
}
printf("After the while loop!\n");
return 0;
}
You can declare a global flag variable and set it to false initially.
Whenever a thread reaches its last statement it sets the flag to true. And whenever a thread starts executing it will first check the flag value, if it false i.e. no other thread has updated it continues execution else returns from the function
First of all you might want to read the pthread_cancel manual page (and the manual pages for the associated pthread_setcancelstate and pthread_setcanceltype functions). The first link contains a nice example.
Another solution is to have e.g. a set of global variables that the threads checks from time to time to see if they should exit or if another thread have exited.
The problem with using e.g. pthread_cancel is that the thread is terminated without letting you clean up after your self easily, which can lead to resource leaks. Read about pthread_key_create about one way to overcome this.

Resources