English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Поскольку неясно, кто из процессов начнет выполнение раньше, это зависит от алгоритма调度 процессов ядра, который очень сложен. Поэтому возможно, что несколько процессов будут одновременно доступ к общей памяти в одно и то же время, что может привести к непредсказуемым ошибкам. Название семафора звучит очень загадочно, но если посмотреть на его английский перевод, становится легко понять.
semaphore [ˈseməfɔ:(r)] vt. выдавать сигнал, поднимать флаг;
Это похоже на роль командира.
Давайте рассмотрим использование семафора в следующем псевдокоде.
1. Создание уникального идентификатора семафора
$ftok = ftok(__FILE__, 'a');
2. Создание идентификатора ресурса семафора
$sem_resouce_id = sem_get($ftok);
3. Получение семафора
sem_acqure($sem_resource_id);
4. Освобождение семафора
sem_release($sem_resource_id);
5. Уничтожение семафора
sem_remove($sem_resource_id);
Давайте рассмотрим нецензурный пример, чтобы сделать более понятным использование семафора в жизни. Поняв это, можно применить это к нашей программированию.
В одной компании есть только один туалет. Поэтому, когда кто-то использует туалет, нужно получить замок (семафор), чтобы показать, что туалет занят. Код следующий:
sem_acqure($sem_resource_id);
После того как сотрудник закончит использовать туалет, нужно открыть замок, освободить замок (семафор), чтобы показать, что теперь можно разрешить другим использовать его. Код следующий:
sem_release($sem_resource_id);
С помощью простого замка мы можем определить, можно ли использовать текущий туалет (общую память). Этот пример не очень приличный, но он объясняет проблему. Этот блог также имеет специфический запах, это действительно不容易。。。。Вот пример кода:
<?php //создание области общей памяти $shm_key = ftok(__FILE__, 'a'); $shm_id = shm_attach($shm_key, 1024, 0755); //var_dump($shm_id);die(); ресурс (4) типа (sysvshm) const SHARE_KEY = 1; $child_list = []; //вход в семафор $sem_id = ftok(__FILE__, 'b'); $signal = sem_get($sem_id); //ресурс сигнала (5) типа (sysvsem) for ($i = 0; $i < 3; $i++) { $pid = pcntl_fork(); exit("Fork fail!".PHP_EOL); elseif ($pid == 0) { } //Получение семафора sem_acquire($signal); if (shm_has_var($shm_id,SHARE_KEY)) { $count = shm_get_var($shm_id, SHARE_KEY); $count++; //Имитация бизнес-обработки $sec = rand(1, 3); sleep($sec); shm_put_var($shm_id, SHARE_KEY, $count); } $count = 0; $sec = rand(1, 3); sleep($sec); shm_put_var($shm_id, SHARE_KEY, $count); } echo "child process: ".getmypid()." is writing! now count is: $count ".PHP_EOL; //Освобождение семафора sem_release($signal); exit("child process".getmypid()."end".PHP_EOL); } $child_list[] = $pid; } } while (count($child_list) > 0) { foreach ($child_list as $key => $pid) { $status = pcntl_waitpid($pid, $status); if ($status > 0 || $status == -1) { unset($child_list[$key]); } } sleep(1); } $count = shm_get_var($shm_id, SHARE_KEY); echo " $count ".PHP_EOL; //Уничтожение семафора sem_remove($signal); shm_remove($shm_id); shm_detach($shm_id);