Семафор — это конструкция синхронизации, используемая в операционных системах для управления доступом к общим ресурсам между несколькими процессами или потоками. По сути, это переменная или абстрактный тип данных, который обеспечивает две основные операции: «ожидание» и «сигнал» (также известные как операции «P» и «V» соответственно).
Вот как работают семафоры:
Операция ожидания (P): Когда процесс/поток хочет получить доступ к общему ресурсу, он сначала выполняет операцию «ожидания» на семафоре, связанном с этим ресурсом. Если значение семафора положительное (больше 0), оно уменьшается на 1 и доступ к ресурсу продолжается. Если значение семафора равно нулю, что указывает на то, что ресурс в настоящее время используется другим процессом/потоком, процесс/поток блокируется или приостанавливается до тех пор, пока семафор не станет доступным.
Сигнальная операция (V): когда процесс/поток завершает использование общего ресурса, он выполняет «сигнальную» операцию на семафоре, которая увеличивает значение семафора на 1. Эта операция указывает, что ресурс теперь доступен для других процессов/потоков. ожидание этого. Если есть какие-либо заблокированные процессы/потоки, ожидающие семафора, один из них пробуждается и ему предоставляется доступ к ресурсу.
Семафоры обеспечивают механизм принудительного взаимного исключения и предотвращения условий гонки, гарантируя, что только один процесс/поток может получить доступ к общему ресурсу в каждый момент времени. Они обычно используются в таких сценариях, как управление доступом к критическим разделам кода, управление одновременным доступом к общим структурам данных и реализация механизмов синхронизации, таких как блокировки и барьеры.
Семафоры могут быть реализованы либо как счетные семафоры (допускающие неотрицательные целые значения), либо как двоичные семафоры (со значениями, ограниченными 0 и 1), в зависимости от конкретных требований синхронизации.
#include <stdio.h> #include <pthread.h> typedef struct { pthread_mutex_t mutex; pthread_cond_t condition; int value; } semaphore; void semaphore_init(semaphore* sem, int initial_value) { pthread_mutex_init(&(sem->mutex), NULL); pthread_cond_init(&(sem->condition), NULL); sem->value = initial_value; } void semaphore_wait(semaphore* sem) { pthread_mutex_lock(&(sem->mutex)); while (sem->value <= 0) { pthread_cond_wait(&(sem->condition), &(sem->mutex)); } sem->value--; pthread_mutex_unlock(&(sem->mutex)); } void semaphore_signal(semaphore* sem) { pthread_mutex_lock(&(sem->mutex)); sem->value++; pthread_cond_signal(&(sem->condition)); pthread_mutex_unlock(&(sem->mutex)); } void* thread_function(void* arg) { semaphore* sem = (semaphore*)arg; printf("Thread waiting\n"); semaphore_wait(sem); printf("Thread acquired the semaphore\n"); // Perform some critical section or shared resource access here printf("Thread releasing the semaphore\n"); semaphore_signal(sem); return NULL; } int main() { semaphore sem; semaphore_init(&sem, 1); // Initialize the semaphore with initial value 1 pthread_t thread; pthread_create(&thread, NULL, thread_function, (void*)&sem); // Main thread also performs some work printf("Main thread performing some work\n"); // Main thread waits for the semaphore printf("Main thread waiting\n"); semaphore_wait(&sem); printf("Main thread acquired the semaphore\n"); // Perform some critical section or shared resource access here printf("Main thread releasing the semaphore\n"); semaphore_signal(&sem); pthread_join(thread, NULL); return 0; }
Надеюсь, вам понравилось это.