This article mainly introduced the PHP program in the file lock, mutual exclusion lock, read-write lock using skills analysis, which focuses on the Sync module and pthreads module use examples, the need for friends can refer to. We hope to help you.
File lock
Full name advisory file lock, which is mentioned in the book. This type of lock is more common, such as MySQL, after php-fpm boot, there will be a PID file record the process ID, this file is a file lock.
This lock prevents a process from running repeatedly, such as qualifying every minute of a task when using crontab, but the process can run for more than a minute, and if a process lock is not used to resolve the conflict, there will be a problem with two processes executing together.
Using a PID file lock also has the advantage of allowing the process to stop or restart the signal itself. For example, the command to restart PHP-FPM is
KILL-USR2 ' Cat/usr/local/php/var/run/php-fpm.pid '
The process of sending the USR2 signal to the PID file record, the signal belongs to the process communication, will open another space.
PHP interface is flock, the document is more detailed. First look at the definition, bool flock (resource $handle, int $operation [, int & $wouldblock]).
The $handle is a file system pointer, which is a resource (resource) typically created by fopen (). This means that you must open a file using flock.
$operation is the type of operation.
& $wouldblock If the lock is blocked, the variable is set to 1.
It is important to note that this function is blocked by default, and if you want non-blocking you can add a bitmask lock_nb to the operation. Next Test.
$pid _file = "/tmp/process.pid"; $pid = Posix_getpid (); $fp = fopen ($pid _file, ' w+ '); if (Flock ($fp, LOCK_EX | LOCK_NB) { echo "got the lock \ n"; Ftruncate ($fp, 0); Truncate file fwrite ($fp, $pid); Fflush ($FP); Flush output before releasing the lock Sleep,//long running Process flock ($fp, lock_un); Release Lock} else { echo "cannot get PID lock. The process is already up \ n ";} Fclose ($FP);
Save As process.php, run PHP process.php &, and then run PHP process.php again to see the error message. Flock also has a shared lock, lock_sh.
mutexes and read-write locks
The mutex in the Sync module:
A mutex is a combination of words, mutual exclusion. Install the Sync module with PECL and pecl installed sync. The Syncmutex in the document is only two methods, lock and unlock, and we'll go straight to the code test. Do not write with the IDE, so the CS is unusually ugly, please ignore.
$mutex = new Syncmutex ("UniqueName"); for ($i =0; $i <2; $i + +) { $pid = Pcntl_fork (); if ($pid <0) {die ("fork Failed"); } ElseIf ($pid >0) { echo "parent process \ n"; } else{ echo "child process {$i} is born. \ n "; Obtainlock ($mutex, $i);} } while (pcntl_waitpid (0, $status)! =-1) { $status = Pcntl_wexitstatus ($status); echo "Child $status completed\n"; }function Obtainlock ($mutex, $i) { echo "process {$i} is getting the mutex \ n"; $res = $mutex->lock (+); Sleep (1); if (! $res) { echo "process {$i} Unable to lock mutex. \ n "; } else{ echo "process {$i} successfully got the mutex \ n"; $mutex->unlock (); } Exit ();}
Save As mutex.php, run PHP mutex.php, output is
Parent process Parent Process Child Process 1 is born. Process 1 is getting the mutex child process 0 is born. Process 0 is getting the mutex process 1 successfully got the mutex child 0 completedprocess 0 Unable to lock mutex. Child 0 completed
Here child processes 0 and 1 are not necessarily who are in front. But there's always one that can't be locked. Here the Syncmutex::lock (int $millisecond) parameter is millisecond, which represents the length of the block, and 1 is an infinite block.
Read and write locks in the Sync module:
Syncreaderwriter method Similar, Readlock, Readunlock, Writelock, Writeunlock, in pairs appear can, did not write the test code, should and the mutex code consistent, the lock can be replaced.
event in the Sync module:
It feels like the cond in Golang, wait () blocks, and fire () wakes up the event blocking a process. There is a good article introduced cond, you can see that cond is a fixed use of locks. The same is true of syncevent.
The example in the PHP documentation shows that the fire () method seems to work in a Web application.
On the test code
for ($i =0; $i <3; $i + +) { $pid = Pcntl_fork (); if ($pid <0) {die ("fork Failed"); } ElseIf ($pid >0) { //echo "parent process \ n"; } else{ echo "child process {$i} is born. \ n "; Switch ($i) {case 0: wait (); break; Case 1: wait (); break; Case 2: sleep (1); Fire (); Break;}}} while (pcntl_waitpid (0, $status)! =-1) { $status = Pcntl_wexitstatus ($status); echo "Child $status completed\n"; }function Wait () { $event = new Syncevent ("UniqueName"); echo "before waiting. \ n "; $event->wait (); echo "After waiting. \ n "; Exit ();} function Fire () { $event = new Syncevent ("UniqueName"); $event->fire (); Exit ();}
There is a deliberate lack of writing a fire (), so the program blocks and proves that fire () wakes up only one process at a time.
Pthreads Module
Locking and unlocking mutexes:
Function:
Pthread_mutex_lock (Mutex) pthread_mutex_trylock (mutex) Pthread_mutex_unlock (mutex)
Usage:
The thread uses the Pthread_mutex_lock () function to lock the specified mutex variable, and if the mutex is already locked by another thread, the call will block the thread until the mutex is unlocked.
Pthread_mutex_trylock () would attempt to lock a mutex. However, if the mutex is already locked, the routine would return immediately with a "busy" error code. This routine is useful in pthread_mutex_trylock ().
Try to lock a mutex, however, if the mutex is locked, the program returns immediately and returns a busy error value. This function is useful for blocking deadlocks in the event of a priority change. Threads can use Pthread_mutex_unlock () to unlock the amount of mutex they occupy. This function can be called when one thread completes the use of the protected data, while other threads are getting mutexes to work on the protected data. If there is a situation, an error will occur:
Mutexes are not so "magical", in fact, they are the "gentlemen's bargain" of participating threads. When writing code, be sure to lock correctly and unlock the mutex.
Q: There are multiple threads waiting for the same locked mutex, and when the mutex is unlocked, that thread will first lock the mutex?
A: Unless the thread uses a priority scheduling mechanism, the thread will be allocated by the system scheduler, and that thread will be the first to lock the mutex is random.
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> typedef structs ct_sum {int sum; pthread_mutex_t lock; }ct_sum; void * ADD1 (void *cnt) {Pthread_mutex_lock (& ((ct_sum*) CNT)->lock); for (int i=0; i <; i++) {(* (ct_sum*) CNT). sum + = i; } Pthread_mutex_unlock (& ((ct_sum*) CNT)->lock); Pthread_exit (NULL); return 0; } void * ADD2 (void *cnt) {Pthread_mutex_lock (& ((ct_sum*) CNT)->lock); for (int i=50; i<101; i++) {(* (ct_sum*) CNT). sum + = i; } Pthread_mutex_unlock (& ((ct_sum*) CNT)->lock); Pthread_exit (NULL); return 0; } int main (void) {pthread_t ptid1, Ptid2; Ct_sum CNT; Pthread_mutex_init (& (Cnt.lock), NULL); cnt.sum=0; Pthread_create (&ptid1, NULL, Add1, &cnt); Pthread_create (&ptid2, NULL, ADD2, &cnt); Pthread_join (Ptid1,null); Pthread_join (Ptid2,null); printf ("Sum%d\n", cnt.sum); Pthread_mutex_destroy (& (CNT.LOck)); return 0; }
Signal Volume
Signal volume in the Sync module:
The Syncsemaphore document shows that it differs from a mutex in that semaphore can be obtained by multiple processes (or threads) at a time, and the mutex can only be obtained by one at a time. So in Syncsemaphore's constructor, there is a parameter that specifies how many processes the semaphore can get.
Public Syncsemaphore::__construct ([string $name [, Integer $initialval [, BOOL $autounlock]]) is this $initialval (Initia L value)
$lock = new Syncsemaphore ("UniqueName", 2); for ($i =0; $i <2; $i + +) { $pid = Pcntl_fork (); if ($pid <0) {die ("fork Failed"); } ElseIf ($pid >0) { echo "parent process \ n"; } else{ echo "child process {$i} is born. \ n "; Obtainlock ($lock, $i);} } while (pcntl_waitpid (0, $status)! =-1) { $status = Pcntl_wexitstatus ($status); echo "Child $status completed\n"; }function Obtainlock ($lock, $i) { echo "process {$i} is getting the lock \ n"; $res = $lock->lock (+); Sleep (1); if (! $res) { echo "process {$i} Unable to lock lock. \ n "; } else{ echo "process {$i} successfully got the lock \ n"; $lock->unlock (); } Exit ();}
At this time two processes can be locked.
Semaphores in the Sysvsem module
Sem_get Creating semaphores
Sem_remove Delete semaphore (not normally used)
Sem_acquire request to get the semaphore
Sem_release The amount of signal released. And Sem_acquire are used in pairs.
$key = Ftok ('/tmp ', ' C '); $sem = Sem_get ($key); for ($i =0; $i <2; $i + +) { $pid = Pcntl_fork (); if ($pid <0) {die ("fork Failed"); } ElseIf ($pid >0) { //echo "parent process \ n"; } else{ echo "child process {$i} is born. \ n "; Obtainlock ($sem, $i);} } while (pcntl_waitpid (0, $status)! =-1) { $status = Pcntl_wexitstatus ($status); echo "Child $status completed\n"; }sem_remove ($sem); Finally remove the Semfunction obtainlock ($sem, $i) { echo "process {$i} is getting the SEM \ n"; $res = Sem_acquire ($sem, true); Sleep (1); if (! $res) { echo "process {$i} unable to get SEM. \ n"; } else{ echo "process {$i} successfully got the SEM \ n"; Sem_release ($sem); } Exit ();}
Here's a question, Sem_acquire () the second parameter, $nowait, defaults to false, blocking. I set to true, if the lock fails, then the Sem_release will report the warning PHP warning:sem_release (): SysV semaphore 4 (key 0x63000081) is not currently Acqui Red in/home/jason/sysvsem.php on line 33, so here the release operation must be placed in the case of a lock to execute, the previous few examples do not have this problem, do not get lock execution release will not error. Of course, it is best to appear in pairs and make sure that you get the lock and release again.
In addition, ftok the parameter of this method is necessary to explain, the first must be existing, accessable file, generally use the file in the project, the second is a single character string. Returns an int.
Output to
Parent process Parent Process Child Process 1 is born. Process 1 is getting the mutex child process 0 is born. Process 0 is getting the mutex process 1 successfully got the mutex child 0 completedprocess 0 Unable to lock mutex. Child 0 completed
Related recommendations:
Simple Introduction to PHP file Lock and Process lock
PHP File Reading Series method