PHP program in the file lock, mutual exclusion lock, read and write lock use skills analysis _php skills

Source: Internet
Author: User
Tags error code flock fpm mutex semaphore sleep

File lock
The name is advisory file lock, which is mentioned in the book. This type of lock is more common, such as MySQL, PHP-FPM Boot will have a PID file records the process ID, this file is a file lock.

This lock prevents a process from running repeatedly, such as limiting the execution of a task every minute when using crontab, but the process may take more than a minute to run, and two processes can be problematic if a process lock is not used to resolve the conflict.

There is also a benefit of using PID file locks to make it easier for the process to send itself to stop or reboot the signal. For example, the command to restart PHP-FPM

KILL-USR2 ' Cat/usr/local/php/var/run/php-fpm.pid '
Send the USR2 signal to the PID file record process, the signal belongs to the process communication, will open another space.

The PHP interface is flock and the document is more detailed. First look at the definition, bool flock (resource $handle, int $operation [, int & $wouldblock]).

    • $handle is a file system pointer, a resource (resource) that is 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.

Note that this function is blocked by default, and a bitmask lock_nb can be added to the operation if you want to be non-blocking. 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, you can see the error prompts. Flock also has shared locks, lock_sh.

mutexes and read-write locks
mutexes in the Sync module:
a mutex is a combination of words, mutual exclusion. Install the Sync module with PECL, pecl install sync. There are only two methods of Syncmutex in the document, lock and unlock, so let's go directly to the code test. Do not use the IDE to write, so the CS unusually ugly, please disregard.

$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 completed
process 0 Unable to lock Mutex. 
Child 0 completed

Here the sub processes 0 and 1 are not necessarily who are in front. But there's always one that doesn't get locked. Here the Syncmutex::lock (int $millisecond) parameter is millisecond, representing the length of the block,-1 is an infinite block.

Read and write locks in the Sync module:
Syncreaderwriter method is similar, Readlock, Readunlock, Writelock, Writeunlock, in pairs appear can, did not write test code, should be consistent with the code of the mutex, replace the lock can be.

Event in sync module:
The sensation is more like the cond in the Golang, the Wait () block, the fire () wakes up the event blocking process. There is a good article introduced cond, you can see that cond is a fixed use of locks. The same is syncevent.
The example in the PHP document shows that the fire () method looks like it can be used in Web applications.

Test Code on

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 ();
}

Here deliberately write a fire (), so the program blocks, proving that fire () wakes only one process at a time.

Pthreads Module
Lock and Unlock mutex:

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 blocks 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 may 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. A thread can unlock its own mutex by using Pthread_mutex_unlock (). This function can be called when a thread completes the use of the protected data, and other threads want to obtain a mutex that works on protecting the data. If there is a situation, an error occurs:

    • The mutex has been unlocked
    • Mutex consumed by another thread

The mutex is not so "magical", in fact, they are the "gentleman's Pact" of the participating threads. When writing code, be sure to lock it properly and unlock the mutex.

Q: There are multiple threads waiting for the same locked mutex, and when the mutex is unlocked, will the thread lock the mutex first?
A: Unless the thread uses a priority scheduling mechanism, the thread is allocated by the system scheduler, and the first lock mutex is random.

#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> typedef struct C 
  t_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;

 }

The

Semaphore
Semaphore in the Sync module:
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 one at a time. So in the Syncsemaphore constructor, there is a parameter that specifies how many processes the semaphore can be obtained.
Public Syncsemaphore::__construct ([string $name [, Integer $initialval [, BOOL $autounlock]]] is this $initialval (i Nitial 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 point, all two processes can get a lock.

    • Semaphores in the Sysvsem module
    • Sem_get Create semaphore
    • Sem_remove Delete semaphore (generally not used)
    • Sem_acquire request to get Semaphore
    • Sem_release releases the semaphore. 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 SEM function 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 problem, Sem_acquire () The second argument $nowait default to False, blocking. I set to true, if the lock fails, then the Sem_release will report warning to PHP Warning:sem_release (): SysV semaphore 4 (key 0x63000081) is not currently Acqu Ired in/home/jason/sysvsem.php on line 33, so the release operation here has to be done with the lock, which is not the case in the previous examples, and does not get a lock to execute release. Of course, it is better to appear in pairs to ensure that the lock is given in case of release.
In addition, it is necessary to ftok the parameters of this method, the first must be existing, accessable files, generally use the files in the project, the second is a single character string. Returns an int.

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 completed
process 0 Unable to lock Mutex. 
Child 0 completed

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.