Maison  >  Article  >  développement back-end  >  Explication détaillée des sémaphores PHP

Explication détaillée des sémaphores PHP

*文
*文original
2017-12-29 18:04:001613parcourir

Cet article présente principalement l'utilisation de base des sémaphores PHP et analyse plus en détail les concepts de base, les compétences d'utilisation et les précautions associées des sémaphores PHP. Les amis dans le besoin peuvent s'y référer. J'espère que cela aide tout le monde.

Les détails sont les suivants :

Quelques bases théoriques :

Sémaphore : également appelé sémaphore et sémaphore, utilisé pour résoudre les processus (problème de synchronisation des threads), similaire à un verrou, acquérir le verrou avant d'accéder (attendre s'il n'est pas acquis) et libérer le verrou après l'accès.
Ressources critiques : ressources auxquelles un seul processus est autorisé à accéder à la fois.
Section critique : Le code qui accède aux ressources critiques dans chaque processus est appelé la section critique
Exclusion mutuelle des processus : Deux processus ou plus ne peuvent pas entrer dans le même processus au même moment. en même temps La zone critique d'une variable partagée de groupe, c'est-à-dire qu'un processus accède à une ressource critique et qu'un autre processus doit attendre avant d'y accéder.
Synchronisation des processusÉtudie principalement comment déterminer l'ordre d'exécution entre plusieurs processus et éviter les problèmes de concurrence des données, c'est-à-dire comment faire en sorte que plusieurs processus fonctionnent ensemble

Exemple Exemple : (de Encyclopédie Baidu)

Prenons l'exemple de l'exploitation d'un parking. Pour simplifier, supposons qu’il n’y a que trois places de stationnement dans le parking et que les trois places de stationnement sont vides au début. À ce moment-là, si cinq voitures arrivent en même temps, le portier permettra à trois d'entre elles d'entrer directement, puis déposera le bloc de voitures. Les voitures restantes doivent attendre à l'entrée, et les voitures suivantes devront également attendre à. l'entrée. À ce moment-là, une voiture a quitté le parking. Après que le gardien l'ait appris, il a ouvert la barrière de la voiture et a mis la voiture à l'extérieur, si deux voitures supplémentaires partaient, il pourrait en mettre deux autres, et ainsi de suite.

Dans ce système de parking, les places de stationnement sont des ressources publiques. Chaque voiture est comme un fil, et le gardien agit comme un sémaphore.


$key=ftok(__FILE__,'t');
/**
 * 获取一个信号量资源
 int $key [, int $max_acquire = 1 [, int $perm = 0666 [, int $auto_release = 1 ]]] 
 $max_acquire:最多可以多少个进程同时获取信号
 $perm:权限 默认 0666
 $auto_release:是否自动释放信号量
 */
$sem_id=sem_get($key);
#获取信号
sem_acquire($seg_id);
//do something 这里是一个原子性操作
//释放信号量
sem_release($seg_id);
//把次信号从系统中移除
sem_remove($sem_id);
//可能出现的问题
$fp = sem_get(fileinode(__DIR__), 100);
sem_acquire($fp);
$fp2 = sem_get(fileinode(__DIR__), 1));
sem_acquire($fp2);

Implémentation d'un sémaphore lecture-écriture en PHP :


class rw_semaphore {
  const READ_ACCESS = 0;
  const WRITE_ACCESS = 1;  
  /**
   * @access private
   * @var resource - mutex semaphore
   */
  private $mutex;
  /**
   * @access private
   * @var resource - read/write semaphore
   */
  private $resource;
  /**
   * @access private
   * @var int
   */
  private $writers = 0;
  /**
   * @access private
   * @var int
   */
  private $readers = 0;
  /**
   * Default constructor
   * 
   * Initialize the read/write semaphore
   */
  public function __construct() {
    $mutex_key = ftok('/home/cyrus/development/php/sysvipc/rw_semaphore.php', 'm');
    $resource_key = ftok('/home/cyrus/development/php/sysvipc/rw_semaphore.php', 'r');    
    $this->mutex = sem_get($mutex_key, 1);
    $this->resource = sem_get($resource_key, 1);    
  }
  /**
   * Destructor
   * 
   * Remove the read/write semaphore
   */
  public function __destruct() {
    sem_remove($this->mutex);
    sem_remove($this->resource);
  }
  /**
   * Request acess to the resource
   * 
   * @param int $mode
   * @return void
   */
  private function request_access($access_type = self::READ_ACCESS) {  
    if ($access_type == self::WRITE_ACCESS) {
      sem_acquire($this->mutex);
      /* update the writers counter */
      $this->writers++;
      sem_release($this->mutex);      
      sem_acquire($this->resource);
    } else {      
      sem_acquire($this->mutex);      
      if ($this->writers > 0 || $this->readers == 0) {        
        sem_release($this->mutex);        
        sem_acquire($this->resource);        
        sem_acquire($this->mutex);        
      }
      /* update the readers counter */
      $this->readers++;
      sem_release($this->mutex);
    }
  }
  private function request_release($access_type = self::READ_ACCESS) {
    if ($access_type == self::WRITE_ACCESS) {
      sem_acquire($this->mutex);
      /* update the writers counter */
      $this->writers--;
      sem_release($this->mutex);
      sem_release($this->resource);
    } else {
      sem_acquire($this->mutex);
      /* update the readers counter */
      $this->readers--;
      if ($this->readers == 0)
        sem_release($this->resource);
      sem_release($this->mutex);
    }
  }
  /**
   * Request read access to the resource
   * 
   * @return void
   */
  public function read_access() { $this->request_access(self::READ_ACCESS); }
  /**
   * Release read access to the resource
   * 
   * @return void
   */
  public function read_release() { $this->request_release(self::READ_ACCESS); }
  /**
   * Request write access to the resource
   * 
   * @return void
   */
  public function write_access() { $this->request_access(self::WRITE_ACCESS); }
  /**
   * Release write access to the resource
   * 
   * @return void
   */
  public function write_release() { $this->request_release(self::WRITE_ACCESS); }
}

Mémoire partagée + signal Implémenter des opérations atomiques


$SHM_KEY = ftok("/home/joeldg/homeymail/shmtest.php", 'R');
$shmid = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$data = shm_attach($shmid, 1024);
// we now have our shm segment
// lets place a variable in there
shm_put_var ($data, $inmem, "test");
// now lets get it back. we could be in a forked process and still have
// access to this variable.
printf("shared contents: %s\n", shm_get_var($data, $inmem));
shm_detach($data);

Recommandations associées :

Explication détaillée de l'utilisation de la mémoire partagée PHP

Plusieurs méthodes courantes d'exécution asynchrone de PHP

Modèle de prototype de constructeur de PHP Explication détaillée de patron prototype

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn