English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Devido ao fato de que a ordem de execução entre processos não é determinada, depende da algoritmo de escalonamento de processos do núcleo, que é complexo. Portanto, pode haver múltiplos processos acessando a memória compartilhada ao mesmo tempo, causando erros imprevisíveis. O nome 'semaforo' é misterioso, mas sua significação em inglês é fácil de entender.
semaphore 英[ˈseməfɔ:(r)] vt. Emitir sinal, sinalizar;
Semelhante ao papel de um comandante.
Vamos ver o uso de um sinal de código falso a seguir.
1Criar identificador único de semáforo
$ftok = ftok(__FILE__, 'a');
2Criar ID de recurso de semáforo
$sem_resouce_id = sem_get($ftok);
3Aceitar semáforo
sem_acqure($sem_resource_id);
4Liberar semáforo
sem_release($sem_resource_id);
5Destruir semáforo
sem_remove($sem_resource_id);
Vamos dar um exemplo impuro para facilitar a compreensão da utilização da variável de sinal na vida real. Após compreender, podemos aplicá-la ao nosso campo de programação.
Uma empresa tem apenas um banheiro. Portanto, quando alguém usar o banheiro, é necessário obter uma chave de bloqueio (semaforo) para indicar que o banheiro está em uso. O código é o seguinte:
sem_acqure($sem_resource_id);
Depois que os funcionários terminarem de usar o banheiro, é necessário abrir o bloqueio, liberar o bloqueio (semaforo), indicando que agora pode permitir que outros o usem. O código é o seguinte:
sem_release($sem_resource_id);
Através de um simples bloqueio, podemos saber se o banheiro (memória compartilhada) está disponível. Este exemplo é pouco apropriado, mas ilustra o problema. Este blog também tem um sabor peculiar, é difícil de descrever。。。。A seguir está o código de exemplo:
<?php //Criar área de memória compartilhada $shm_key = ftok(__FILE__, 'a'); $shm_id = shm_attach($shm_key, 1024, 0755); //var_dump($shm_id);die(); resource(4) of type (sysvshm) const SHARE_KEY = 1; $child_list = []; //Adicionar semáforo $sem_id = ftok(__FILE__, 'b'); $signal = sem_get($sem_id); //$signal resource(5) of type (sysvsem) for ($i = 0; $i < 3; $i++) { $pid = pcntl_fork(); if ($pid == -1) { exit("Falha de bifurcação!".PHP_EOL); } elseif ($pid == 0) { //Obter sinal sem_acquire($signal); if (shm_has_var($shm_id,SHARE_KEY)) { $count = shm_get_var($shm_id, SHARE_KEY); $count++; //Simulação de processamento de negócios $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 "processo filho: ".getmypid()." está escrevendo! agora o contador é: $count ".PHP_EOL; //Liberar sinal sem_release($signal); exit("processo filho".getmypid()."final".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; //Destruir sinal sem_remove($signal); shm_remove($shm_id); shm_detach($shm_id);