1

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);
    }
}
QChí Nguyễn
  • 273
  • 6
  • 16
  • You have no control over which of the threads will run first. You need to figure out some other way to synchronize the threads. Condition variables maybe? Or multiple mutexes if it's a requirement to use those? – Some programmer dude Dec 19 '16 at 07:48
  • 2
    If you wish for your processes to run "in order", you have no need for threads or mutexes. A mutex is used to prevent multiple threads from writing to the same location, nothing else. – DeiDei Dec 19 '16 at 07:49
  • 2
    On an unrelated note: The declaration `void processA();` doesn't declare a function `processA` which takes no arguments. It declares a function which takes an undefined number of unknown arguments. If you want to explicitly say that a function takes no arguments, then you need to use `void processA(void);` – Some programmer dude Dec 19 '16 at 07:49
  • Either use conditional variable or shared handler to synchronize the all threads. – Sumit Gemini Dec 19 '16 at 07:50
  • Also, don't cast function pointers, but declare your functions correctly such that they fit the required prototype. Functions with different prototype can have different calling conventions and your program can seriously crash with this. A good rule of thumb for C programs is not to use casts at all but to always get the types correct. Casts are evil. – Jens Gustedt Dec 19 '16 at 08:53

2 Answers2

1

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
cokceken
  • 2,068
  • 11
  • 22
  • This is not a good answer in the context the OP put it. Semaphores are only an optional feature in POSIX and in C's thread option they aren't present at all. Use a condition variable, instead. (Also POSIX semaphores are quite tricky to handle correctly because their functions are interruptible.) – Jens Gustedt Dec 19 '16 at 08:54
  • How do you wait for your condition to happen ? isnt it harder then explaining the concept – cokceken Dec 19 '16 at 08:56
  • What to do you mean by "how do you wait?" Using `pthread_cond_wait` respectively `cnd_wait`, obviously. – Jens Gustedt Dec 19 '16 at 09:27
0

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;
}
  • This code has many, many problems. First, [`pthread_cond_wait()` is subject to spurious wakeups](https://stackoverflow.com/questions/8594591/why-does-pthread-cond-wait-have-spurious-wakeups) which you haven't accounted for. Second, the use of `pthread_mutex_lock()` by the main thread can block child threads from executing and cause a deadlock - once the main thread locks mutex `v1`, none of the child threads can run at all. Third, you've ignored the original question's intent to "run in order A, B, C, D". – Andrew Henle Oct 03 '19 at 15:42