0 x01 semaphore

Definition: In computer science, a semaphore is a variable or abstract data type used to control multithreading access to a common resource, avoiding critical section problems in concurrent systems such as multitasking operating systems. A trivial semaphore is an ordinary variable that changes (for example, increases or decreases, or switches) according to conditions defined by the programmer.

0 x02 initialization

We need to initialize the semaphore before operation

#include <semaphore.h>
 sem_t s;
 sem_init(&s, 0, 1);
Copy the code

Sem_init takes three arguments, the first is the address of the variable, the second is 0 for the same process, shared by multiple threads, and the third is the initial value

0 x03 operation

In POSIX standards, operations are defined by two sets of apis: sem_wait() and sem_post()

Sem_wait () means that a thread will either suspend or return immediately (if greater than or equal to 1) until POST is called, but multiple threads will call WAIT, and any thread that does not meet the criteria will be queued

Sem_post () indicates that if there are waiting threads in the wait queue, one of them will be woken up, and if the semaphore is negative, how many threads are waiting

0 x04 application

Semaphores are widely used, and here are two classic scenarios, locks and conditional variables

  • The lock

    • We know that the lock has two states, occupied and non-occupied, then we use the semaphore to represent, defined as 0/1, sem_wait(-1), sem_POST (+1) is surrounded by the protected critical region
       sem_t m;  
       sem_init(&m, 0, 1); 
       sem_wait(&m);
       //  xxx code
       sem_post(&m);
    Copy the code

    Semaphore as lock, the initial value should be set to 1 semaphore as lock, pay attention to scope, improper scope will be a deadlock

  • Condition variables,

    sem_t s;
     void *
     child(void *arg) {
       printf("child\n");
       sem_post(&s); // signal here: child is done
       return NULL;
     }
     
      int
      main(int argc, char *argv[]) {
        sem_init(&s, 0, X); // what should X be?
        printf("parent: begin\n");
        pthread_t c;
        Pthread_create(c, NULL, child, NULL);
        sem_wait(&s); // wait here for child
        printf("parent: end\n");
        return 0;
      }
    Copy the code
  • If we wanted to output something like this, what would be the initial value?

    // parent: begin

    // child

    // parent: end

To satisfy this condition, the parent thread must wait for the child thread to complete, and we need to consider two cases

  • In the first case, the parent thread creates the child thread, but the child thread is not running. If the initial value is 1, after wait,

The parent thread continues to execute, and the child thread may run either before or after the parent thread wait. If the initial value is 0, the parent thread wait must wait, and the child thread POST will wake the parent thread

  • In the second case, the child thread finishes running before the parent thread calls sem_wait(), which satisfies the output and is not considered

0x05 Summary and Abstraction

  • Semaphores can implement locks and condition variables, and vice versa

  • Semaphore idea: If I abstract the semaphore idea, I will associate it with the number line, which is the logarithm demarcation, so that the number definition is separated, so that we can achieve the desired effect

  • When dealing with concurrency, sometimes the simple principle is better, need to lock when there is a lock, semaphore although can achieve the effect, but need from the semaphore -> lock, more than a step, not as direct lock to clear semantics

  • The maximum number of database connections can also be achieved by semaphore.

0 x06 reference

  • WIKI
  • Introduction to operating systems
Copy the code