This article mainly introduces the basic usage of PHP semaphores and analyzes in detail the basic concepts, usage skills, and related precautions of PHP semaphores, for more information about how to use a PHP semaphore, see the example in this article. We will share this with you for your reference. The details are as follows:
Some theoretical foundations:
Semaphores: It is also called a signal lamp and a flag to solve the process (thread synchronization problem). It is similar to a lock. get the lock before Access (wait if it cannot be obtained) and release the lock after access.
Critical Resources: Resources that can be accessed by only one process at a time.
Critical section: The code used to access critical resources in each process is called a critical zone.
Process mutex: Two or more processes cannot enter the critical area of the same group of shared variables at the same time, that is, one process is accessing critical resources, and the other process must wait for access.
Process synchronizationThis article mainly studies how to determine the execution sequence between several processes and avoid data competition, that is, how to enable a good cooperative operation of multiple processes.
Example: (from Baidu Encyclopedia)
Take the operation of a parking lot as an example. For simplicity, assume that there are only three parking spaces in the parking lot, and the three parking spaces are empty at the beginning. At this time, if there are five vehicles at the same time, the gatekeeper will allow three of them to enter directly, and then put down the car, the remaining cars will have to wait at the entrance, and the cars that come later will have to wait at the entrance. At this time, a car left the parking lot. after the gatekeeper learned it, he opened the car and put it in another car. if he left the car again, he could put it in two more cars.
In this parking lot system, a parking space is a public resource. every car is like a thread. The gatekeeper plays the role of a semaphore.
$ Key = ftok (_ FILE __, 'T');/*** get a semaphore resource int $ key [, int $ max_acquire = 1 [, int $ perm = 0666 [, int $ auto_release = 1] $ max_acquire: the maximum number of processes that can receive signals at the same time $ perm: default permission 0666 $ auto_release: whether to automatically release the Semaphore */$ sem_id = sem_get ($ key); # obtain the signal sem_acquire ($ seg_id ); // do something here is an atomic operation // release The semaphores sem_release ($ seg_id); // remove sem_remove ($ sem_id) from the system ); // possible problems $ fp = sem_get (fileinode (_ DIR _), 100); sem_acquire ($ fp ); $ fp2 = sem_get (fileinode (_ DIR _), 1); sem_acquire ($ fp2 );
Implementation of a read-write semaphore in 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); }}
Shared memory + signal for atomic operations
$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 thereshm_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);
The above column sub-source php manual sem_get function comment