Home > Back-end >  How to use semaphores to control progress of 2 threads?
How to use semaphores to control progress of 2 threads?

Time:12-04

I learned the concept of semaphore. And I'm trying to implement it. I've been trying to implement it for over 19 hours, but I can't do it, so I'm writing to ask for your help.

It checks the progress of the current two threads, just as it does with CV, and if both threads output entered, it can resume the subsequent operation.

Below is the full text of the code. `

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>



void *child1(void *arg) {
    printf("child thread 1 entered!\n");
    // call semaphoreshere here

    printf("child thread 1 exits!\n");
    return NULL;
}

void *child2(void *arg) {
    printf("child thread 2: entered!\n");
    // call semaphores here

    printf("child thread 2: exits\n");
    return NULL;
}

int main(int argc, char *argv[]) {
    pthread_t p1, p2;
    printf("parent thread: begin\n");
    // init semaphores here
    // // sem_init(&empty, 0, 0); 
    // // sem_init(&full, 0, 0); //Code tried but not working properly



    pthread_create(&p1, NULL, child1, NULL);
    pthread_create(&p2, NULL, child2, NULL);
    pthread_join(p1, NULL);
    pthread_join(p2, NULL);
    printf("parent thread: end\n");
    return 0;
}

` Using ONLY TWO semaphores within the code, this attempts to control the thread's internal execution order so that both threads must output the ~~entered message before it can exit.

The execution result I want is as follows.

>>>
parent thread: begin
child thread 1 entered!
child thread 2: entered!
child thread 2: exits
child thread 1 exits!
parent thread: end

>>>
parent thread: begin
child thread 2 entered!
child thread 1: entered!
child thread 1: exits
child thread 2 exits!
parent thread: end

Like this, I want to implement only the role of monitoring each other to see if they've entered.

I'd appreciate your help. thanks.

CodePudding user response:

What you want to do (in semaphoore-thinking) is:

  • thread 1 waits till thread 2 is done before it exits.
  • thread 2 waits till thread 1 is done before it exits.

Which leads to the following code, which I modified a bit because I cannot stand global variables.

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>

typedef struct SharedContext_tag {
  sem_t t1done;
  sem_t t2done;
} SharedContext_t;

void *child1(void* arg) {
  SharedContext_t* ctx = (SharedContext_t*) arg;
  printf("child thread 1: entered!\n");
  sem_post(&ctx->t1done);
  sem_wait(&ctx->t2done);
  printf("child thread 1 exits!\n");
  return NULL;
}

void *child2(void* arg) {
  SharedContext_t* ctx = (SharedContext_t*) arg;  
  printf("child thread 2: entered!\n");
  sem_post(&ctx->t2done);
  sem_wait(&ctx->t1done);
  printf("child thread 2: exits!\n");
  return NULL;
}

int main(int argc, const char* argv[]) {
  pthread_t p1;
  pthread_t p2;
  SharedContext_t context;
  sem_init(&context.t1done, 0, 0);
  sem_init(&context.t2done, 0, 0);
  printf("parent thread: begin\n");
  pthread_create(&p1, NULL, child1, &context);
  pthread_create(&p2, NULL, child2, &context);
  pthread_join(p1, NULL);
  pthread_join(p2, NULL);
  printf("parent thread: end\n");
  sem_close(&context.t1done);
  sem_close(&context.t2done);
  return 0;  
}

On my machine at this time (being careful here!), the output is as required:

> ./sema
parent thread: begin
child thread 1: entered!
child thread 2: entered!
child thread 2: exits!
child thread 1 exits!
parent thread: end

In order for it to work, you need to link against the real-time library, librt. You do so by adding -pthread to your compile command.

> clang-13 -g -O0 -pthread -o sema sema.c
  • Related