I have 4 processed called A, B, C, D in 4 thread, They printf their name. I want use mutex to process A, B, C, D run in order A, B, C, D. This is my code but it don't work such as me think. How to they work?
#include <stdio.h>
#include <pthread.h>
void processA();
void processB();
void processC();
void processD();
pthread_mutex_t mutex;
void main(){
pthread_t thread1;
pthread_t thread2;
pthread_t thread3;
pthread_t thread4;
pthread_mutex_init(&mutex,NULL);
pthread_create(&thread1, NULL, (void *)&processA,NULL);
pthread_create(&thread2, NULL, (void *)&processB,NULL);
pthread_create(&thread3, NULL, (void *)&processC,NULL);
pthread_create(&thread4, NULL, (void *)&processD,NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
pthread_join(thread4, NULL);
pthread_mutex_destroy(&mutex);
}
void processA()
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("A \n");
pthread_mutex_unlock(&mutex);
}
}
void processB()
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("B \n");
pthread_mutex_unlock(&mutex);
}
}
void processC()
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("C \n");
pthread_mutex_unlock(&mutex);
}
}
void processD()
{
pthread_mutex_lock(&mutex);
while (1)
{
pthread_mutex_lock(&mutex);
printf("D \n");
pthread_mutex_unlock(&mutex);
}
}
mutex is for creating mutual exclusion on some context. For example if you have an object that should be reached by one thread at a time, you can use mutex.
You should use 3 semaphores for implementing such feature. You can say:
//semaphore1 = up, semaphore2 = up, semaphore3 = up
//Thread A
//wait for semaphore1 is up
//work
//make semaphore1 down
//Thread B
//wait for semaphore1 is down
//work
//make semaphore2 down
//Thread C
//wait for semaphore2 is down
//work
//make semaphore3 down
//Thread D
//wait for semaphore3 is down
//work
Well this is how you can do it, you just use mutex for the mutual variable (f in this case) and a pthread conditional signal to trigger the action of one thread per second. All of the threads get the signal but only one can access the mutex.
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <stdarg.h>
#include <pthread.h>
pthread_mutex_t v1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t v2 = PTHREAD_COND_INITIALIZER;
int f = 0;
void *processA(){
while(1){
pthread_mutex_lock(&v1);
pthread_cond_wait(&v2,&v1);
printf("A,%d\n",f);
f++;
pthread_mutex_unlock(&v1);
}
return NULL;
}
void *processB(){
while(1){
pthread_mutex_lock(&v1);
pthread_cond_wait(&v2,&v1);
printf("B,%d\n",f);
f++;
pthread_mutex_unlock(&v1);
}
return NULL;
}
void *processC(){
while(1){
pthread_mutex_lock(&v1);
pthread_cond_wait(&v2,&v1);
printf("C,%d\n",f);
f++;
pthread_mutex_unlock(&v1);
}
void main(){
pthread_t *h;
int i,ptnum = 3;
h = malloc(sizeof(pthread_t)*ptnum);
pthread_create(&h[0],NULL,processA,NULL);
pthread_create(&h[1],NULL,processB,NULL);
pthread_create(&h[2],NULL,processC,NULL);
while(f<=30){
pthread_cond_signal(&v2);
sleep(1);
}
pthread_mutex_lock(&v1);
printf("Main Mutex\n");
for(i=0;i<ptnum;i++){
pthread_join(&h[i],PTHREAD_CANCELED);
}
pthread_mutex_unlock(&v1);
return NULL;
}
Related
This is the code I have so far for the newly modified version of nosmp.c.
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
lng t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
The code below is the old nosmp.c code:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* thread(void* arg)
{
printf("\n Entered.., %c\n", *((char*)arg));
//critical section
sleep(4);
printf("\n Just Exiting.., %c\n", *((char*)arg));
}
int main()
{
pthread_t t1,t2;
pthread_create(&t1,NULL,thread,"1");
sleep(2);
pthread_create(&t2,NULL,thread,"2");
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
For the modified version of the code above, I am trying to figure out where I would add the semaphore system calls into their proper lines to ensure that two threads will enter the critical section in order.
It gets me error at rand_r
undefined reference to 'rand_r'
It is my first program at c language
I must use rand_r to threads, but i don't know what to do.
Please help me. Thank you
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "p3160062.h"
int cook;
int oven;
int prep;
int bake;
pthread_mutex_t lock;
pthread_t thread_id[100];
unsigned int seed;
int a;
void *myThread(void *vargp)
{
pthread_mutex_lock(&lock);
a=rand_r(&seed)%6;
while(a==0){
a=rand_r(&seed)%6;
}
printf("a=%d\n",a);
sleep(1);
printf("In thread\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(void)
{
seed=1;
int i=0;
printf("Before Thread\n");
for(i=0;i<100;i++){
pthread_create(&(thread_id[i]), NULL, myThread, NULL);
pthread_join(thread_id[i], NULL);
seed++;
}
printf("After Thread\n");
pthread_mutex_destroy(&lock);
exit(0);
}
I'm learning to handle threads deadlock, but by executing the C code on my terminal, execution does not generate deadlocks even if it should. Can anyone tell me why and possibly how to force the deadlock?
#include<pthread.h>
#include<semaphore.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void *func(void *p);
pthread_mutex_t m1,m2;
int main(){
pthread_t tid[2];
pthread_attr_t attr;
pthread_attr_init(&attr);
int id[2];
for(int i=0;i<2;i++){
id[i]=i;
pthread_create(&tid[i],&attr,func,(&id[i]));
}
pause();
}
void *func(void *p){
int *i=p;
while(1){
if(*i==0){
pthread_mutex_lock(&m1);
pthread_mutex_lock(&m2);
printf("I'm Thread %d\n", *i);
pthread_mutex_unlock(&m1);
pthread_mutex_unlock(&m2);
}
else{
pthread_mutex_lock(&m2);
pthread_mutex_lock(&m1);
printf("I'm Thread %d\n", *i);
pthread_mutex_unlock(&m1);
pthread_mutex_unlock(&m2);
}
}
pthread_exit(0);
}
Change the assignment of the variable in your thread:
int *i=(int *)p;
You need to point to the argument else both threads run the same lock unlock sequence. Where you call pthread_create there is a implicit cast.
I could not figure out how to get your code to deadlock. I was able to get the following example to deadlock on macOS:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
typedef struct {
const char *mutex_name;
pthread_mutex_t *pmutex;
} mutex_data_t;
typedef struct {
const char *thread_name;
mutex_data_t mutex_list[2];
} thread_data_t;
void *deadlock(void *data) {
thread_data_t *pthread_data = data;
const char *name = pthread_data->thread_name;
printf("%s: Starting...\n", name);
printf("%s: Locking %s...\n", name, pthread_data->mutex_list[0].mutex_name);
pthread_mutex_lock(pthread_data->mutex_list[0].pmutex);
printf("%s: Sleeping...\n", name);
sleep(1);
printf("%s: Locking %s...\n", name, pthread_data->mutex_list[1].mutex_name);
pthread_mutex_lock(pthread_data->mutex_list[1].pmutex);
printf("Done\n");
return NULL;
}
int main()
{
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
mutex_data_t mutex1_data = { "mutex1", &mutex1 };
mutex_data_t mutex2_data = { "mutex2", &mutex2 };
thread_data_t thread1_data = { "thread1", { mutex1_data, mutex2_data }};
thread_data_t thread2_data = { "thread2", { mutex2_data, mutex1_data }};
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
pthread_create(&thread1, NULL, deadlock, &thread1_data);
pthread_create(&thread2, NULL, deadlock, &thread2_data);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
Output
thread1: Starting...
thread2: Starting...
thread1: Locking mutex1...
thread2: Locking mutex2...
thread1: Sleeping...
thread2: Sleeping...
thread1: Locking mutex2...
thread2: Locking mutex1...
I am been trying to write a program (for learning) in which there will be two threads (A and B) and both threads should execute one after the another. For example, if threads just display/prints Thread A and Thread B, then they should print in that particular order forever.
The desired output is
In Thread: thread1
In Thread: thread2
In Thread: thread1
In Thread: thread2
....
The program that I have wrote uses conditional variables for synchronisation. I have tired mutex and semaphore but they do guarantee mutual exclusivity but they don't print the information in a particular order. I understand that issue is related to scheduling of the threads by scheduler and it is possible that the thread which has just released the mutex, can lock it again immediately. See this link for link for more information.
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
pthread_cond_t cond;
pthread_mutex_t mutex;
int thread1_ret = 0;
void *thread1(void *arg)
{
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("In Thread: %s\r\n", __func__);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
thread1_ret = 5;
return &thread1_ret;
}
int thread2_ret = 0;
void *thread2(void *arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("In Thread: %s\r\n", __func__);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
thread2_ret = 5;
return &thread2_ret;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_create(&t1, &attr, thread1, NULL);
pthread_create(&t2, &attr, thread2, NULL);
pthread_attr_destroy(&attr);
void *ret;
pthread_join(t1, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
pthread_join(t2, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
return 0;
}
My program is working properly but it stops printing after some time (2-3 seconds). I couldn't locate the bug in my code. It would be great if someone direct me with some other solution to achieve the same thing in more efficient and standard method (if there are other standard and efficient methods to solve such problem statement).
Condition variable notifications get lost when no thread is waiting in pthread_cond_wait and spurious wakes-ups happen, so the code must rather wait for a change of a shared state.
Working example:
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned state = 0;
int thread1_ret = 0;
void *thread1(void *arg)
{
unsigned state_copy;
pthread_mutex_lock(&mutex);
state_copy = state;
pthread_mutex_unlock(&mutex);
while(1) {
pthread_mutex_lock(&mutex);
while(state_copy == state)
pthread_cond_wait(&cond, &mutex);
state_copy = ++state;
printf("In Thread: %s\r\n", __func__);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
thread1_ret = 5;
return &thread1_ret;
}
int thread2_ret = 0;
void *thread2(void *arg)
{
unsigned state_copy;
pthread_mutex_lock(&mutex);
state_copy = ++state;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
while (1) {
pthread_mutex_lock(&mutex);
while(state_copy == state)
pthread_cond_wait(&cond, &mutex);
state_copy = ++state;
printf("In Thread: %s\r\n", __func__);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
thread2_ret = 5;
return &thread2_ret;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
void *ret;
pthread_join(t1, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
pthread_join(t2, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
return 0;
}
Note that the above code signals the condition variable after releasing the mutex. That is a micro-optimization, however, if FIFO order in waking up waiting threads is required then the mutex must be locked while signalling. See pthread_cond_signal:
The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal().
I want to print for infinity the below message "What a wonderful world!" , I have from the begin the 3 threads to do this job the first one "What a , second one "Wonderful" and third one "world" , ( I am giving as parameter in ./a.out 3) , the problem in the below code is that the message displayed like this : What a wonderful what a wonderful the World is missing. I think Something is bad with the conditional variables, any suggestions?
int p;
void *disp(void *arg);
pthread_mutex_t muta,mutb,mutc;
pthread_cond_t condition_cond= PTHREAD_COND_INITIALIZER;
void *disp(void *arg)
{
int id=*(int*)arg;
free(arg);
arg=0;
pthread_mutex_lock(&muta);
while (id==0)
{
pthread_cond_wait (&condition_cond,&muta);
}
printf("What a");
pthread_mutex_unlock(&muta);
pthread_mutex_lock(&mutb);
while (id==1)
{
pthread_cond_wait (&condition_cond,&mutb);
}
printf(" Wonderful");
pthread_mutex_unlock(&mutb);
pthread_mutex_lock(&mutc);
while(id==2)
{
pthread_cond_wait (&condition_cond,&mutc);
}
printf(" World!\n");
pthread_mutex_unlock(&mutc);
return NULL;
}
EDIT: updated code based on the answer by dbush:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
int p;
void *disp(void *arg);
pthread_mutex_t mut=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1= PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2= PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3= PTHREAD_COND_INITIALIZER;
void *disp(void *arg)
{
int id=*(int*)arg;
free(arg);
arg=0;
pthread_mutex_lock(&mut);
while(1)
{
if (id==0)
{
pthread_cond_wait (&cond1,&mut);
printf("What a ");
pthread_cond_signal (&cond2);
}
else if(id==1)
{
pthread_cond_wait (&cond2,&mut);
printf(" wonderful ");
pthread_cond_signal (&cond3);
}
else if(id==2)
{
pthread_cond_wait (&cond3,&mut);
printf(" world!\n ");
pthread_cond_signal (&cond1);
}
}
return NULL;
}
int main (int argc,char *argv[])
{
int i;
pthread_t *tid;
if(argc!=2)
{
printf("Provide number of threads.\n");
exit(1);
}
p=atoi(argv[1]);
tid=(pthread_t *) malloc (p*sizeof(pthread_t));
if (tid==NULL)
{
printf("Could not allocate memory.\n");
exit(1);
}
for (i=0;i<p;++i)
{
int *a;
a=malloc(sizeof(int)); //pointer to pass
*a=i;
pthread_create(&tid[i],NULL,disp,a);
}
pthread_cond_signal(&cond1);
for (i=0;i<p;++i)
pthread_join(tid[i],NULL);
return 0;
}
You've got your usage of mutexes and condition variables reversed. You need one mutex to control all three threads, and three condition variables (one for each thread).
After each thread finishes its work, it should signal the next thread using the condition variable for the target thread. Additionally, the main function needs to signal the first thread to get things started. You'll want it to sleep for a brief period so that all threads have time to start.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void *disp(void *arg);
pthread_mutex_t mux = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1= PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2= PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3= PTHREAD_COND_INITIALIZER;
void *disp(void *arg)
{
int id=*(int*)arg;
free(arg);
arg=0;
pthread_mutex_lock(&mux);
while (1) {
if (id==0) {
pthread_cond_wait (&cond1,&mux);
printf("What a");
pthread_cond_signal(&cond2);
} else if (id == 1) {
pthread_cond_wait (&cond2,&mux);
printf(" Wonderful");
pthread_cond_signal(&cond3);
} else if (id == 2) {
pthread_cond_wait (&cond3,&mux);
printf(" World!\n");
pthread_cond_signal(&cond1);
}
}
return NULL;
}
int main()
{
pthread_t t1, t2, t3;
int *id = malloc(sizeof(int));
*id=0;
pthread_create(&t1, NULL, disp, id);
id = malloc(sizeof(int));
*id=1;
pthread_create(&t2, NULL, disp, id);
id = malloc(sizeof(int));
*id=2;
pthread_create(&t3, NULL, disp, id);
sleep(1);
pthread_cond_signal(&cond1);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
return 0;
}