For the wait operation, if the non-negative integer variable S of the semaphore is greater than 0, wait will subtract 1, and if S is equal to 0, wait will block the calling thread; For the post operation, if a thread is blocked on the semaphore (at this time, s is equal to 0), post will unblock a waiting thread and make it return from the waiting state. If there is no thread blocking on the semaphore, post will add s to 1.
In this way, s can be understood as the number of a resource, and semaphores achieve mutual exclusion and synchronization by controlling the allocation of such resources. If s is set to 1, then semaphore can make multiple threads run concurrently. In addition, semaphore not only allows users to apply for and release resources, but also allows users to create resources, which gives semaphore synchronization function. It can be seen that the functions of semaphores are much richer than mutexes.
POSIX semaphore is a variable of sem_t type, but POSIX has two implementation mechanisms: anonymous semaphore and named semaphore. Nameless semaphores can only be used when * * * has memory, such as mutual exclusion and synchronization between threads in the process, so nameless semaphores are also called memory-based semaphores; Named semaphores are usually used when memory is unavailable, such as inter-process communication.
At the same time, when creating semaphores, POSIX semaphores can be divided into:
The following is the POSIX semaphore function interface:
The functions of semaphores all start with sem_, and there are four basic signal functions used in the thread, all of which are declared in the header file semaphore.h, which defines the sem_t type used for semaphore operation:
Sem_init function:
This function is used to create semaphores, and the prototype is as follows:
This function initializes the signal object pointed by sem, sets its * * * option, and gives it an initial integer value. Pshared controls the type of semaphore. If its value is 0, it means that the semaphore is the local semaphore of the current process, otherwise it can be shared among multiple processes, and value is the initial value of sem.
This function returns 0 on success and-1 on failure.
Sem_destroy function:
This function is used to clean up used semaphores, and its prototype is as follows:
0 returned successfully,-1 failed.
Sem_wait function:
This function is used to subtract 1 from the value of the semaphore by atomic operation. Atomic operation means that if two threads try to add 1 or subtract 1 to a semaphore at the same time, they will not interfere with each other. Its prototype is as follows:
The object pointed by sem is the semaphore initialized by sem_init call. Returns 0 on success and-1 on failure.
Sem_trywait () is a non-blocking version of sem_wait (). When the condition is not met (when the semaphore is 0), the function directly returns an EAGAIN error without blocking the wait.
The function of sem_timedwait () is similar to that of sem_wait (), except that it waits within the specified abs_timeout time, and if it exceeds the time, it directly returns an ETIMEDOUT error.
Sem_post function:
This function is used to add 1 to the value of semaphore by atomic operation. Its prototype is as follows:
Like sem_wait, the object that sem points to is the semaphore initialized by sem_init call. Returns 0 on success and-1 on failure.
Sem_getvalue function:
This function returns the value of the current semaphore through the restrict output parameter. If the current semaphore is locked (that is, the synchronization object is unavailable), the return value is 0 or negative, and its absolute value is the number of threads waiting for the semaphore to be unlocked.
Example 1:
Example 2:
It is called a named semaphore because it has a name, a user ID, a group ID and permissions. These interfaces provide named semaphores for processes that do not occupy memory. The name of the named semaphore is a string that follows the rules of path name construction.
Sem_open function:
This function is used to create or open a named semaphore, and its prototype is as follows:
The parameter name is a string that identifies the semaphore. Parameter oflag is used to determine whether to create a semaphore or connect an existing semaphore.
The parameter of oflag can be 0, O_CREAT or O_EXCL: If it is 0, it means to open an existing semaphore; If it is O_CREAT, it means that if the semaphore does not exist, a semaphore is created, and if it exists, it is opened and returned. At this point, both mode and value need to be specified; If it is O_CREAT|O_EXCL, it means that the semaphore exists and an error is returned.
The mode parameter is used to specify the permission bit of the semaphore when it is created. Like the open function, it includes: S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH.
Value indicates the initial value of the semaphore when it is created.
Sem_close function:
This function is used to turn off named semaphores:
A single program can close the specified semaphore with sem_close function, but it cannot delete the semaphore from the system because the specified semaphore is persistent outside the execution of a single program. When the process calls _exit, exit, exec or returns from main, the named semaphore opened by the process will also be closed.
Sem_unlink function:
The sem_unlink function is used to delete a semaphore from the system after all processes close the specified semaphore:
Semaphore operation function:
Like anonymous semaphores, the functions for manipulating semaphores are as follows:
Named semaphores are persistent in the kernel. When creating a named semaphore, even if no process is currently opening it, its value will remain until the kernel restarts or calls sem_unlink () to delete the semaphore.
The persistence of anonymous semaphores depends on their location in memory:
Many times, semaphores, mutexes and conditional variables can be used in some applications. What is the difference between them? The differences between the three are listed below: